<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>В лабиринте извилин</title>
	
	<link>http://www.charnad.com</link>
	<description>Блог-центр им. CharnaD</description>
	<lastBuildDate>Sat, 12 May 2012 12:00:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/charnad" /><feedburner:info uri="charnad" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>SDL: Как создать игру. Сущности.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/Trt8S133DPk/</link>
		<comments>http://www.charnad.com/blog/sdl-tutorial-6-entities/#comments</comments>
		<pubDate>Sat, 12 May 2012 12:00:33 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[entities]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1469</guid>
		<description><![CDATA[Это вольный перевод и переосмысление статьи, SDL Tutorial - Animation за авторством Tim Jones. Готовый код я буду выкладывать на Github, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы. В этой [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="SDL" />Это вольный перевод и переосмысление статьи, <a href="http://www.sdltutorials.com/sdl-animation">SDL Tutorial - Animation</a> за авторством Tim Jones. Готовый код я буду выкладывать на <a href="https://github.com/charnad/SDLTutorial">Github</a>, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы.</p>
<p>В этой статьей мы направим наши силы на создание сущностей (Entities). Сущности - это все, с чем можно взаимодействовать. Например, это может быть монстр или сундук с сокровищами, который можно открыть. В этом смысле, практически все в игре, что движется, это сущность. Камень, который является частью карты, который никогда не двигается, не является сущностью. Но если вы хотите, чтобы камень двигался, не важно по какой причине, то мы сделаем его сущностью.<span id="more-1469"></span></p>
<p>Давайте начнем с создания двух новых файлов: <strong>Entity.cpp</strong> и <strong>Entity.h</strong>. Откройте заголовочный файл и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &lt;vector&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;Animation.h&quot;</span>
<span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Entity <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">static</span> std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span>Entity<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span>    EntityList<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">protected</span><span style="color: #008080;">:</span>
        Animation      Anim<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Surface<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">float</span>           X<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">float</span>           Y<span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">int</span>             Width<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span>             Height<span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">int</span>             AnimState<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Entity<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> ~Entity<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">bool</span> Load<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File, <span style="color: #0000ff;">int</span> Width, <span style="color: #0000ff;">int</span> Height, <span style="color: #0000ff;">int</span> MaxFrames<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Теперь откройте Entity.cpp и добавьте это:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Entity.h&quot;</span>
&nbsp;
std<span style="color: #008080;">::</span><span style="color: #007788;">vector</span><span style="color: #000080;">&lt;</span>Entity<span style="color: #000040;">*</span><span style="color: #000080;">&gt;</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008080;">;</span>
&nbsp;
Entity<span style="color: #008080;">::</span><span style="color: #007788;">Entity</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Surface <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
    X <span style="color: #000080;">=</span> Y <span style="color: #000080;">=</span> <span style="color:#800080;">0.0f</span><span style="color: #008080;">;</span>
&nbsp;
    Width <span style="color: #000080;">=</span> Height <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
    AnimState <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
Entity<span style="color: #008080;">::</span>~Entity<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File, <span style="color: #0000ff;">int</span> Width, <span style="color: #0000ff;">int</span> Height, <span style="color: #0000ff;">int</span> MaxFrames<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Surface <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span>File<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>Surface, <span style="color: #0000dd;">255</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">255</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Width <span style="color: #000080;">=</span> Width<span style="color: #008080;">;</span>
    this<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Height <span style="color: #000080;">=</span> Height<span style="color: #008080;">;</span>
&nbsp;
    Anim.<span style="color: #007788;">MaxFrames</span> <span style="color: #000080;">=</span> MaxFrames<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">Loop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Anim.<span style="color: #007788;">Animate</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Screen<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Surface <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span> <span style="color: #000040;">||</span> Screen <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
&nbsp;
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, Surface, X, Y, AnimState <span style="color: #000040;">*</span> Width, Anim.<span style="color: #007788;">GetCurrentFrame</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> Height, Width, Height<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">Cleanup</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Surface<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        SDL_FreeSurface<span style="color: #008000;">&#40;</span>Surface<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Surface <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Теперь поясню. В этом классе мы инкапсулируем 5 основных компонентов, о которых я упоминал в первой статье. Это позволит нам работать с сущностями в игре гораздо проще, чем смешивать их в кучу со всем остальным в классе App. Первое, что вы можете заметить, это статический вектор, который называется EntityList. Этот вектор будет содержать все наши сущности, они будут легко доступны через Entity::EntityList, потому что он объявлен статическим. Надо особо отметить: мы объявляем EntityList в Entity, поскольку это предотвратит циклические зависимости в будущем. То есть, например мы попытаемся получить карту, чтобы обработать сущности на ней, а также хотим получить сущности, чтобы обработать карту. Map объявляет Entity, Entity объявляет Map, это повлечет за собой проблемы во время компиляции.</p>
<p>Так что этот вектор содержит все наши сущности в игре. Обратите внимание, что каждый член вектора - указатель. Это потому, что в дальнейшем мы будем наследовать все последующие классы сущностей от класса Entity. Так, например, если мы собираемся сделать игру Megaman, мы бы создали класс Megaman и унаследовали бы его от класс Entity. И, благодаря полиморфизму, мы можем хранить объекты класса Megaman в EntityList. Собственно поэтому, мы заявили функции в классе, как virtual, а некоторые члены как protected. </p>
<p>Далее, у нас есть базовая информация о сущности, общая для всех: координаты, размеры, поверхность для ее(сущности) изображения. Также, у нас есть функция загрузки, она получает имя файла и загружает изображение из него. По умолчанию, устанавливается прозрачный цвет. Я хочу чтобы вы понимали, что все, что я делаю не высечено в камне. Вы можете, и я даже советую вам менять код по своему вкусу. Вы можете передавать функции Load больше или меньше параметров, может вы не хотите устанавливать прозрачность по умолчанию, кто знает. Пробуйте и не волнуйтесь, если где-то запутаетесь или ошибетесь, вы всегда сможете достать мой код.</p>
<p>Итак, у нас есть основная функция Loop, которая обрабатывает основные расчеты. Сейчас мы только занимаемся анимацией. Мы лишь меняем  MaxFrames, а остальное оставляем по умолчанию. Далее, функция Render, в качестве параметра передается поверхность для отображения. Чтобы можно было рисовать не только сразу на экран, но и на любую другую поверхность по вашему выбору. Ну и наконец, функция Cleanup, которая освобождает память и все такое. </p>
<p>Как я уже говорил в начале, это лишь базовая структура класса Entity, она еще может не так много, но не волнуйтесь, в будущем сможет сделать все, что вы захотите. Итак, давайте заставим сущности работать. Откройте <strong>App.h</strong> и добавьте файл заголовка в начале, и объявить две сущности:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Entity.h&quot;</span>
&nbsp;
<span style="color: #666666;">//...</span>
&nbsp;
<span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
    Entity         Entity1<span style="color: #008080;">;</span>
    Entity         Entity2<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Давайте теперь загрузим в них изображения, в App::Init.cpp добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Entity1.<span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/yoshi.bmp&quot;</span>, <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">8</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Entity2.<span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/yoshi.bmp&quot;</span>, <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">8</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
Entity2.<span style="color: #007788;">X</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span><span style="color: #008080;">;</span>
&nbsp;
Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span>.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>Entity1<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span>.<span style="color: #007788;">push_back</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>Entity2<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Я еще раз использую изображение Йоши и прошлой статьи.</p>
<p>Вспомните, что я говорил, про инкапсуляцию основных функции игры в классе Entity. Мы должны вызывать эти функции в соответствующих функциях App. Поэтому, откройте App::Loop и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span>.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
&nbsp;
    Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Мы в обходим каждый элемент вектора и вызываем функцию Loop. Довольно просто. (И мы проверяем на NULL, чтобы не было ошибок). Теперь, давайте сделаем то же самое в App::Render:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span>.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
&nbsp;
    Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Render<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>и еще раз то же самое в App::Cleanup:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span>.<span style="color: #007788;">size</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #000040;">!</span>Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">continue</span><span style="color: #008080;">;</span>
&nbsp;
    Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span><span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span><span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
Entity<span style="color: #008080;">::</span><span style="color: #007788;">EntityList</span>.<span style="color: #007788;">clear</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Обратите внимание, я добавил вызов функции очистки вектора.</p>
<p>Отлично, теперь скомпилируйте то, что получилось. Вы должны увидеть две фигурки Йоши на экране. В следующей статье мы рассмотрим создание карты.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/sdl-tutorial-6-entities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/sdl-tutorial-6-entities/</feedburner:origLink></item>
		<item>
		<title>SDL: Как создать игру. Анимация.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/DK7IPm4akqI/</link>
		<comments>http://www.charnad.com/blog/sdl-tutorial-5-animation/#comments</comments>
		<pubDate>Sun, 06 May 2012 21:50:12 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1434</guid>
		<description><![CDATA[Это вольный перевод и переосмысление статьи, SDL Tutorial - Animation за авторством Tim Jones. Готовый код я буду выкладывать на Github, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы. В последней [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="SDL" />Это вольный перевод и переосмысление статьи, <a href="http://www.sdltutorials.com/sdl-animation">SDL Tutorial - Animation</a> за авторством Tim Jones. Готовый код я буду выкладывать на <a href="https://github.com/charnad/SDLTutorial">Github</a>, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы.</p>
<p>В последней статье мы создали прототип игры в крестики-нолики. Надеюсь, многие из вас смогли заставить его работать. Если нет, то не волнуйтесь, рано или поздно у вас все получится. В этой статье мы собираемся научиться делать анимацию с помощью SDL. Как и прежде, мы будем код предыдущих статей SDL, за исключением кода из Крестиков-ноликов. Я отменил почти все изменения, сделанные в той статье, оставил лишь Transparent функцию для класса Sprite.</p>
<p>Мы создадим новый класс для обработки анимации, и в следующем уроке мы создадим класс для сущностей (Entities). Имейте в виду, что эти две разные вещи, и, хотя я знаю, они могут быть выражены через один класс, я не хочу использовать такой подход. Поэтому, пожалуйста, попридержите вашу критику.<span id="more-1434"></span></p>
<p>Создайте два новых файла с названиями <strong>Animation.h</strong> и <strong>Animation.cpp</strong>. В будущем, наш Entity-класс будет наследовать этот класс, но пока что мы будем пользоваться им напрямую. Давайте сразу подключим файл в <strong>App.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Animation.h&quot;</span></pre></td></tr></table></div>

<p>Теперь откройте <strong>Animation.h</strong> и добавьте базовую структуру класса в файл:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _ANIMATION_H_</span>
<span style="color: #339900;">#define _ANIMATION_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Animation <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">int</span>    CurrentFrame<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span>     FrameInc<span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">int</span>     FrameRate<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">long</span>    OldTime<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">int</span>    MaxFrames<span style="color: #008080;">;</span>
        <span style="color: #0000ff;">bool</span>    Oscillate<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Animation<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Animate<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">void</span> SetFrameRate<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> Rate<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> SetCurrentFrame<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> Frame<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> GetCurrentFrame<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Теперь откройте <strong>Animation.cpp</strong> и добавьте следующий код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Animation.h&quot;</span>
&nbsp;
Animation<span style="color: #008080;">::</span><span style="color: #007788;">Animation</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    CurrentFrame    <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    MaxFrames       <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    FrameInc        <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
&nbsp;
    FrameRate       <span style="color: #000080;">=</span> <span style="color: #0000dd;">100</span><span style="color: #008080;">;</span> <span style="color: #666666;">//Milliseconds</span>
    OldTime         <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
    Oscillate       <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Animation<span style="color: #008080;">::</span><span style="color: #007788;">Animate</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>OldTime <span style="color: #000040;">+</span> FrameRate <span style="color: #000080;">&gt;</span> SDL_GetTicks<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    OldTime <span style="color: #000080;">=</span> SDL_GetTicks<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    CurrentFrame <span style="color: #000040;">+</span><span style="color: #000080;">=</span> FrameInc<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Oscillate<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>FrameInc <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>CurrentFrame <span style="color: #000080;">&gt;=</span> MaxFrames<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
                FrameInc <span style="color: #000080;">=</span> <span style="color: #000040;">-</span>FrameInc<span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span><span style="color: #0000ff;">else</span><span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>CurrentFrame <span style="color: #000080;">&lt;=</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
                FrameInc <span style="color: #000080;">=</span> <span style="color: #000040;">-</span>FrameInc<span style="color: #008080;">;</span>
            <span style="color: #008000;">&#125;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span><span style="color: #0000ff;">else</span><span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>CurrentFrame <span style="color: #000080;">&gt;=</span> MaxFrames<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
            CurrentFrame <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Animation<span style="color: #008080;">::</span><span style="color: #007788;">SetFrameRate</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> Rate<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    FrameRate <span style="color: #000080;">=</span> Rate<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Animation<span style="color: #008080;">::</span><span style="color: #007788;">SetCurrentFrame</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> Frame<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Frame <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #000040;">||</span> Frame <span style="color: #000080;">&gt;=</span> MaxFrames<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
&nbsp;
    CurrentFrame <span style="color: #000080;">=</span> Frame<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> Animation<span style="color: #008080;">::</span><span style="color: #007788;">GetCurrentFrame</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> CurrentFrame<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Теперь объясню что же делает этот класс. Существует один основной элемент анимации, который мы должны обрабатывать - текущий кадр анимации. Возьмите изображение Йоши ниже (мы будем использовать его в этой статье). Вы увидите, у нас есть 8 кадров Йоши на одном изображении. Каждый кадр будет пронумерован 0, 1, 2 сверху вниз. </p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/5/yoshi.bmp"></p>
<p>Помните, статью про координаты, где мы создаели функцию, которая отрисовывает часть изображения? И если взять эту функцию в сочетании с номером кадра анимации, вуаля!</p>
<p>Первая переменная, CurrentFrame, это текущий кадр анимации, который мы будем рисовать на экране. Независимо от того, какое у него значение, он будет определять, какую часть поверхности мы будем рисовать на экране. Поэтому, когда мы вызываем функцию рисования, мы делаем что-то вроде этого:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, Image, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span>, Anim_Yoshi.<span style="color: #007788;">GetCurrentFrame</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">64</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Так как наш Йоши размером 64 х 64 пикселей, столько мы и захватим для вывода, это же и является нашим кадром анимации. Посмотрите на иллюстрацию ниже.</p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/5/Animation.jpg"/></p>
<p>Когда CurrentFrame увеличивается на 1, мы прыгаем вниз на 64 пикселя (высота кадра Yoshi), и рисуем этот кадр. </p>
<p>Другая часть этого класса нужна нам для того, чтобы определять, сколько кадров в анимации - MaxFrames. Наконец важно так же знать, сколько кадров в секунду, или, скорее, как быстро будет меняться анимированное изображение. Для этого мы используем вот этот кусок кода в функции Animate().</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>OldTime <span style="color: #000040;">+</span> FrameRate <span style="color: #000080;">&gt;</span> SDL_GetTicks<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Если взять OldTime в миллисекундах плюс желаемую частоту кадров, мы можем сравнить это значение с количеством миллисекунл, которые SDL был запущен. Например, мы только что запустили нашу программу, SDL_GetTicks = 0, и OldTime = 0. Желаемая частота кадров будет 1 кадр в секунду. Итак FrameRate = 1000 (миллисекунд). 0 + 1000 больше 0? Да, так что мы не будем ничего делать и ждать. Но как только 0 + 1000 станет меньше, чем SDL_GetTicks, что означает, что 1 секунда прошла, мы увеличим номер кадра, а затем сбросим OldTime на текущее время, и начнем все сначала. </p>
<p>Следующий интересный момент это Oscillate и FrameInc. Я не хотел бы никого путать лишними переменными, но мне кажется, что это пригодится нам в будущем. В общем, когда Oscillate = true, в анимация будет увеличиваться номер кадра, а затем уменьшаться в обратном порядке. Если бы в анимации было 10 кадров, было бы как-то так: </p>
<p>0 1 2 3 4 5 6 7 8 9 8 7 6 5 4 3 2 1 2 ... </p>
<p>Видите, номер кадра идет до 9, а затем уменьшается обратно до 0, и так далее. Есть несколько интересных применений для этого, но мы этим займемся в других статьях. Так, как это работает? Взгляните на функцию Animate. Если Oscillate = false, то мы просто проверяем превысил ли номер текущего кадра максимальное количество кадров. Если да - сбрасываем на 0, а затем ниже, мы переходим к следующему кадру. В противположном же случае, у нас есть переменная FrameInc, которая принимает значения 1 или -1, в зависимости от того, увеличиваем или уменьшаем номер кадра. То есть, если FrameInc больше 0, мы увеличиваем номер кадра, иначе - уменьшаем. И если мы достигли первого или последнего кадра - меняем FrameInc на противоположный. </p>
<p>Теперь, когда мы обо всем позаботились, используем этот класс. Создайте новый объект типа Animation в <strong>App.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">Animation      Anim_Yoshi<span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Теперь, давайте установиv MaxFrames, добавьте в App::Init():</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>Test, <span style="color: #0000dd;">255</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">255</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
Anim_Yoshi.<span style="color: #007788;">MaxFrames</span> <span style="color: #000080;">=</span> <span style="color: #0000dd;">8</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>И теперь, чтобы анимация двигалась в App::Loop():</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">Anim_Yoshi.<span style="color: #007788;">Animate</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>И наконец, нарисуем на экране App::Render():</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    SDL_FillRect<span style="color: #008000;">&#40;</span>Screen, <span style="color: #0000ff;">NULL</span>, <span style="color: #208080;">0x000000</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, Test, <span style="color: #0000dd;">290</span>, <span style="color: #0000dd;">220</span>, <span style="color: #0000dd;">0</span>, Anim_Yoshi.<span style="color: #007788;">GetCurrentFrame</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">64</span>, <span style="color: #0000dd;">64</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    SDL_Flip<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Теперь скомпилируйте и смотрить как работает наша анимация! SDL_FillRect заполняет указанную поверхность одним цветом, в данном случае черным, чтобы остатки анимации не мешались на экране.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/sdl-tutorial-5-animation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/sdl-tutorial-5-animation/</feedburner:origLink></item>
		<item>
		<title>SDL: Как создать игру. Крестики-нолики.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/KdxV0DcbHg4/</link>
		<comments>http://www.charnad.com/blog/sdl-tutorial-4-tic-tac-toe/#comments</comments>
		<pubDate>Fri, 04 May 2012 23:18:20 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1416</guid>
		<description><![CDATA[Это вольный перевод и переосмысление статьи, SDL Tutorial - Tic Tac Toe за авторством Tim Jones. Готовый код я буду выкладывать на Github, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы. [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="SDL" />Это вольный перевод и переосмысление статьи, <a href="http://www.sdltutorials.com/sdl-tutorial-tic-tac-toe">SDL Tutorial - Tic Tac Toe</a> за авторством Tim Jones. Готовый код я буду выкладывать на <a href="https://github.com/charnad/SDLTutorial">Github</a>, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы.</p>
<p>До этого момента мы закладывали основу для создания игры. Мы создавали базовую структуру для обработки общих задач, создали специальный класс для обработки событий, и создали класс для работы с поверхностями. В этом уроке мы их объединим для создания игры в крестики-нолики. Не волнуйтесь, все будет довольно просто. Будем использовать код из последней статьи.<span id="more-1416"></span></p>
<p>Первое, что мы надо сделать - спланировать игру. Все мы знаем, что крестики-нолики имеют поле 3x3, где игроки ставят крестики или нолики. Итак, для этого нам будет нужно 3 изображения, одно для игрового поля, одно для X, и одно для О. Нам не нужно многокрестиков или ноликов, потому что мы можем отрисовывать их в программе сколько угодно раз. Наше игровое поле будет размером 600x600, а наши X и O будут 200x200 (1/3 площади). </p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/4/grid.png"/><br />
<img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/4/o.png" style="float: left;"/><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/4/x.png"/><br />
<br clear="both">[<i>Это png изображения, для работы вам нужны bmp. Их можно взять в репозитории на гитхабе, ссылка в начале поста.</i>]</p>
<p>Теперь у нас есть изображения, и нам нужен способ, чтобы загрузить их в нашу программу. Откройте <strong>App.h</strong> и внесите некоторые изменения. Удалите поверхность Test, и добавьте три новых поверхности.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;Event.h&quot;</span>
<span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Event <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>            Running<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Screen<span style="color: #008080;">;</span>
&nbsp;
        SDL_Surface<span style="color: #000040;">*</span>    G<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    X<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    O<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Evt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Exit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Далее, откройте <strong>App.cpp</strong> и проделайте то же самое, удалите Test и добавьте три новых поверхности. В конструкторе:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">App<span style="color: #008080;">::</span><span style="color: #007788;">App</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    G <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    X <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    O <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    Screen <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
    Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>и не забудьте об освобождении ресурсов:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Cleanup</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>G<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>X<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>O<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_Quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Теперь у нас есть три готовые поверхности, давайте загрузим туда изображения. Найдите App::Init(), и внесите изменения: избавимся от поверхности Test (опять), и загрузим три новых изображения. Обратите внимание, что мы изменили размер окна до размеров игрового поля - 600х600.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SDL_Init<span style="color: #008000;">&#40;</span>SDL_INIT_EVERYTHING<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Screen <span style="color: #000080;">=</span> SDL_SetVideoMode<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">32</span>, SDL_HWSURFACE <span style="color: #000040;">|</span> SDL_DOUBLEBUF<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>G <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/grid.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>X <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/x.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>O <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/o.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Как вы могли заметить, теперь графические файлы находятся в папке gfx. Со временем, когда игра растет, становится очень удобно держать все изображения в одной папке. Давайте теперь нарисуем игровое поле на экране. Откройте App::Render.cpp и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, G, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    SDL_Flip<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Скомпилируйте программу, и если все хорошо - вы должны увидеть игровое поле. Помните, что есть 5 основных моментов использования поверхностей: объявить ее, установите ее в NULL, загрузите изображение, нарисуйте поверхность, а затем освободите ее. Я советую вам, запомнить эти 5 шагов сейчас, потому что позже, если вы пропустите один из них, вы можете столкнуться с проблемами. Например, не установленная в NULL поверхность, может привести к непредсказуемому поведению или, не освобожденная поверхность, может привести к утечке памяти. </p>
<p>Вы наверняка удивляетесь, почему наши X и O на розовом фоне. Для этого, конечно же, есть причина. Мы собираемся реализовать прозрачность у этих поверхностей. По существу, везде, где сейчас розовый цвет, поверхность будет прозрачной. В SDL есть простая функция для этого SDL_SetColorKey. Давайте добавим ее в <strong>Sprite.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _SPRITE_H_</span>
<span style="color: #339900;">#define _SPRITE_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Sprite <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Sprite<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">static</span> SDL_Surface<span style="color: #000040;">*</span> Load<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> Draw<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> Draw<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y, <span style="color: #0000ff;">int</span> X2, <span style="color: #0000ff;">int</span> Y2, <span style="color: #0000ff;">int</span> W, <span style="color: #0000ff;">int</span> H<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> Transparent<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Surface, <span style="color: #0000ff;">int</span> R, <span style="color: #0000ff;">int</span> G, <span style="color: #0000ff;">int</span> B<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Теперь, в <strong>Sprite.cpp</strong> добавим ее реализацию:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Surface, <span style="color: #0000ff;">int</span> R, <span style="color: #0000ff;">int</span> G, <span style="color: #0000ff;">int</span> B<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Surface <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    SDL_SetColorKey<span style="color: #008000;">&#40;</span>Surface, SDL_SRCCOLORKEY <span style="color: #000040;">|</span> SDL_RLEACCEL, SDL_MapRGB<span style="color: #008000;">&#40;</span>Surface<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>format, R, G, B<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Обратите внимание на 3 дополнительных параметра, которые передаются помимо поверхности. Эти параметры обозначают цвет, в системе RGB, который мы хотим сделать прозрачным, это не обязательно должен быть розовый. Например, если бы мы хотели, чтобы прозрачным был красный, то передали бы в функцию: 255, 0, 0.</p>
<p>Функция Transparent сначала проверяет, есть ли у нас действительная поверхность. Если да, то установливает цветовой ключ[<i>aka <a href="http://ru.wikipedia.org/wiki/%D5%F0%EE%EC%E0%EA%E5%E9">хромакей</a></i>] (прозрачность). Первым аргументом идет поверхность к которой применяется хромакей, вторым параметром идут различные флаги, а третьим цвет, который будет прозрачным. Флаги, которые мы передаем вполне обычные, первый говорит SDL применять хромакей для переданной поверхности, а второй говорит SDL попытаться использовать RLE ускорение (чтобы сделать отрисовку быстрее). Третий аргумент выглядит чуть более сложным, мы используем SDL_MapRGB для создания цвета. SDL_MapRGB принимает параметром поверхность, и желаемый цвет (R, G, B), и подобрать наиболее близкий к нему для этой поверхности. Не все поверхности имеют одинаковую цветовую палитру. Вспомните старые времена Денди, там можно было использовать всего несколько цветов. Та же идея здесь, SDL_MapRGB берет цвет и сопоставляет его с ближайшим цветом в палитре этой поверхности. </p>
<p>Давайте теперь применим эту новую функцию к нашим поверхностям, откройте App::Init и внесите следующие изменения:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SDL_Init<span style="color: #008000;">&#40;</span>SDL_INIT_EVERYTHING<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Screen <span style="color: #000080;">=</span> SDL_SetVideoMode<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">32</span>, SDL_HWSURFACE <span style="color: #000040;">|</span> SDL_DOUBLEBUF<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>G <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/grid.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>X <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/x.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>O <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/o.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>X, <span style="color: #0000dd;">255</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">255</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>O, <span style="color: #0000dd;">255</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">255</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Теперь все, что касается поверхностей, должно быть готово. Следующее, что нам нужно сделать, это выяснить как рисовать эти X и O. Мы не можем просто рисовать их везде по полю, потому что они не всегда будут в одинаковых местах. И вот что мы сделаем, мы создадим массив из 9 контейнеров, значения в этом массиве будет говорить о том, какая фигура стоит в каждой ячейке клетки, а индекс - номер ячейки. То есть, ячейка с индексом 0 будет в верхнем левом углу, с индексом 1 будет вверху посередине, 2 в правом верхнем углу, 3 в середине слева, и так далее. </p>
<p>Каждая ячейка может иметь три значения: Empty, X, и О. Чтобы все выглядело немного аккуратнее, чем просто 0, 1, 2, в массиве, мы будем использовать перечисление (enum). Обозначим GRID_TYPE_NONE = 0, GRID_TYPE_X = 1, и GRID_TYPE_O = 2. </p>
<p>Теперь добавим массив и перечисление в <strong>App.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;Event.h&quot;</span>
<span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">enum</span> <span style="color: #008000;">&#123;</span>
    GRID_TYPE_NONE <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span>,
    GRID_TYPE_X,
    GRID_TYPE_O
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Event <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>            Running<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Screen<span style="color: #008080;">;</span>
&nbsp;
        SDL_Surface<span style="color: #000040;">*</span>    G<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    X<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    O<span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">int</span>             Grid<span style="color: #008000;">&#91;</span><span style="color: #0000dd;">9</span><span style="color: #008000;">&#93;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Evt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Exit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>С этого момента, я буду давать только код требуемых функций, а не код из файла. Надеюсь, что вы уже запомнили где находятся основные функции, и это не станет проблемой. Нам нужно добавить функцию сброса игрового поля. Она установит все значения массива в GRID_TYPE_NONE, и это будет означать, что все клетки поля пусты. Добавим так же вызов этой функции в инициализацию:</p>
<p>В <strong>App.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
    <span style="color: #0000ff;">void</span> Reset<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>В <strong>App.cpp</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Reset</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">9</span><span style="color: #008080;">;</span>i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        Grid<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> GRID_TYPE_NONE<span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SDL_Init<span style="color: #008000;">&#40;</span>SDL_INIT_EVERYTHING<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Screen <span style="color: #000080;">=</span> SDL_SetVideoMode<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">600</span>, <span style="color: #0000dd;">32</span>, SDL_HWSURFACE <span style="color: #000040;">|</span> SDL_DOUBLEBUF<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>G <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/grid.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>X <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/x.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>O <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;./gfx/o.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>X, <span style="color: #0000dd;">255</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">255</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Transparent</span><span style="color: #008000;">&#40;</span>O, <span style="color: #0000dd;">255</span>, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">255</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    Reset<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Следующее, что мы должны сделать, это функция размещения X и O на экране. Давайте ее создадим. Откройте опять <strong>App.h</strong> и добавьте функцию ниже Reset:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> SetCell<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> ID, <span style="color: #0000ff;">int</span> Type<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>И в <strong>App.cpp</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">SetCell</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> ID, <span style="color: #0000ff;">int</span> Type<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>ID <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #000040;">||</span> ID <span style="color: #000080;">&gt;=</span> <span style="color: #0000dd;">9</span><span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Type <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span> <span style="color: #000040;">||</span> Type <span style="color: #000080;">&gt;</span> GRID_TYPE_O<span style="color: #008000;">&#41;</span> <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
&nbsp;
    Grid<span style="color: #008000;">&#91;</span>ID<span style="color: #008000;">&#93;</span> <span style="color: #000080;">=</span> Type<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Эта функция принимает два аргумента: во-первых, id изменяемой ячейки, а во-вторых тип, в который мы ее устанавливаем. У нас есть два условия, во-первых, убедимся, что мы не выходим за границы массива (иначе наша программа бы упала), а во-вторых, убедимся, что мы задаем правильный тип. Теперь давайте сделаем так, чтобы X и O отрисовывались на экране. Добавим следующий код в <strong>App::Render</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, G, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">for</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> i <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>i <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">9</span><span style="color: #008080;">;</span>i<span style="color: #000040;">++</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">int</span> cX <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>i <span style="color: #000040;">%</span> <span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">200</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> cY <span style="color: #000080;">=</span> <span style="color: #008000;">&#40;</span>i <span style="color: #000040;">/</span> <span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">200</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Grid<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">==</span> GRID_TYPE_X<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
            Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, X, cX, cY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span><span style="color: #0000ff;">else</span>
        <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Grid<span style="color: #008000;">&#91;</span>i<span style="color: #008000;">&#93;</span> <span style="color: #000080;">==</span> GRID_TYPE_O<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
            Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, O, cX, cY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    SDL_Flip<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Это немного сложнее, чем то, что мы делали до сих пор. Во-первых, мы проходим по каждой ячейке поля, переводим ID клетки в X и Y координаты. Чтобы найти X, мы берем остаток от деления на 3. Это даст нам 0, когда i = 0, 1, когда i = 1, 2, когда i = 2, 0, когда i 3, и так далее. Умножим полученное число на 200, потому что каждая клетка размером 200x200 пикселей, и получаем координату X. Чтобы найти Y, мы делим на 3 без остатка, это дает 0, когда i = [0, 1, 2], 1, когда i = [3, 4, 5], и так далее. Затем опять умножаем на 200. Я настоятельно советую вам разобраться, как это работает, потому что методы такого рода используются для tile-based игр.</p>
<p>Наконец, нам нужно обрабатывать пользовательские действия. Для этого мы будем отлавливать события мышки. Когда пользователь нажимает на ячейку будем ставить в нее X или O. Переопределим один из методов Event для этого. Откройте <strong>App.h</strong> и добавьте функцию и переменную, про нее я скажу чуть позже:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> CurrentPlayer<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">void</span> OnLButtonDown<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>И в <strong>App.cpp</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">OnLButtonDown</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> ID <span style="color: #000080;">=</span> mX <span style="color: #000040;">/</span> <span style="color: #0000dd;">200</span><span style="color: #008080;">;</span>
    ID <span style="color: #000080;">=</span> ID <span style="color: #000040;">+</span> <span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>mY <span style="color: #000040;">/</span> <span style="color: #0000dd;">200</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">3</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Grid<span style="color: #008000;">&#91;</span>ID<span style="color: #008000;">&#93;</span> <span style="color: #000040;">!</span><span style="color: #000080;">=</span> GRID_TYPE_NONE<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>CurrentPlayer <span style="color: #000080;">==</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        SetCell<span style="color: #008000;">&#40;</span>ID, GRID_TYPE_X<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        CurrentPlayer <span style="color: #000080;">=</span> <span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span><span style="color: #0000ff;">else</span><span style="color: #008000;">&#123;</span>
        SetCell<span style="color: #008000;">&#40;</span>ID, GRID_TYPE_O<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        CurrentPlayer <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Сначала мы делаем обратное преобразование, из координат в ID. Затем проверяем, что клетка еще не занята, иначе выходим из функции. Потом проверяем, чей сейчас ход, ставим соответствующую фигуру и передаем ход другому игроку. Как раз CurrentPlayer и говорит нам о том, чей сейчас ход. Кстати, ее надо инициализировать в конструкторе в <strong>App.cpp</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">App<span style="color: #008080;">::</span><span style="color: #007788;">App</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    CurrentPlayer <span style="color: #000080;">=</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
&nbsp;
    G <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    X <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    O <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
    Screen <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
    Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Скомпилируйте программу и вы должны получить почти полностью работающую версию крестиков-ноликов. Поздравляем!</p>
<p>Попробуйте дальше сделать самостоятельно. У нас есть прочный фундамент для нашей игры. Попробуйте добавить "X победил", "О победил" и "Ничья" в конце каждой игры (нужны дополнительные изображения). Подумайте, как вы собираетесь определять, кто выиграл. Попробуйте добавить способ сбросить игру после того, как она закончилась. Если хотите, можете даже попробовать добавить некий искуственный интеллект, который будет играть против пользователей. Или, если вам и этого мало, попробуйте добавить возможность играть игрок против игрока, или игрока против компьютера.</p>
<p>Когда у вас будет твердое понимание, как все работает в этой статье - вы можете перейти к следующей, для изучения покадровой анимации.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/sdl-tutorial-4-tic-tac-toe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/sdl-tutorial-4-tic-tac-toe/</feedburner:origLink></item>
		<item>
		<title>SDL: Как создать игру. События.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/jVGTT47lYSw/</link>
		<comments>http://www.charnad.com/blog/sdl-tutorial-3-events/#comments</comments>
		<pubDate>Wed, 02 May 2012 20:51:07 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[events]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1400</guid>
		<description><![CDATA[Это вольный перевод и переосмысление статьи, SDL Events за авторством Tim Jones. Готовый код я буду выкладывать на Github, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы. Говоря об основах разработки [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="SDL" />Это вольный перевод и переосмысление статьи, <a href="http://www.sdltutorials.com/sdl-events">SDL Events</a> за авторством Tim Jones. Готовый код я буду выкладывать на <a href="https://github.com/charnad/SDLTutorial">Github</a>, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы.</p>
<p>Говоря об основах разработки игр нельзя не упомянуть о том, что называется событиями (Events). Все видеоигры, от Pong до очень сложных игр для ПК и консоли, используют события для взаимодействия с игроком. Эти события могут поступать от клавиатуры, мыши, джойстика, геймпада, и так далее, даже из операционной системы. Важно понять, как работают события, если мы хотим позволить пользователю взаимодействовать с игрой. Мы уже использовали события, но только для закрытия нашего окна, теперь мы посмотрим, как получать события от пользователя.</p>
<p>Если вы еще не догадались, каждая статья построена на основе предыдущих, так что будем использовать код из предыдущей статьи. Чтобы отслеживать все эти события и использовать их в наших функциях, давайте создадим новый класс. Создайте два файла с названиями: <strong>Event.h</strong> и <strong>Event.cpp</strong>. Эти два файла будет обрабатывать наши события, и вызвать соответствующую функцию. Класс App будет наследовать этот класс, поэтому, когда нам нужно будет поймать событие мы просто переопределим функцию.<span id="more-1400"></span></p>
<p>Откройте <strong>Event.h</strong> и добавьте следующий код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _EVENT_H_</span>
<span style="color: #339900;">#define _EVENT_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Event <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Event<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> ~Event<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Handle<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnInputFocus<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnInputBlur<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnKeyDown<span style="color: #008000;">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnKeyUp<span style="color: #008000;">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMouseFocus<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMouseBlur<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMouseMove<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY, <span style="color: #0000ff;">int</span> relX, <span style="color: #0000ff;">int</span> relY, <span style="color: #0000ff;">bool</span> Left,<span style="color: #0000ff;">bool</span> Right,<span style="color: #0000ff;">bool</span> Middle<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMouseWheel<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">bool</span> Up, <span style="color: #0000ff;">bool</span> Down<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnLButtonDown<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnLButtonUp<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnRButtonDown<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnRButtonUp<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMButtonDown<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMButtonUp<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnJoyAxis<span style="color: #008000;">&#40;</span>Uint8 which, Uint8 axis, Sint16 value<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnJoyButtonDown<span style="color: #008000;">&#40;</span>Uint8 which, Uint8 button<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnJoyButtonUp<span style="color: #008000;">&#40;</span>Uint8 which, Uint8 button<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnJoyHat<span style="color: #008000;">&#40;</span>Uint8 which, Uint8 hat, Uint8 value<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnJoyBall<span style="color: #008000;">&#40;</span>Uint8 which, Uint8 ball, Sint16 xrel, Sint16 yrel<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnMinimize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnRestore<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnResize<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> w,<span style="color: #0000ff;">int</span> h<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnExpose<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> Exit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">virtual</span> <span style="color: #0000ff;">void</span> OnUser<span style="color: #008000;">&#40;</span>Uint8 type, <span style="color: #0000ff;">int</span> code, <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> data1, <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> data2<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Немаленький класс, да? Так, а теперь откройте <strong>Event.cpp</strong> и добавьте следующий код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Event.h&quot;</span>
&nbsp;
Event<span style="color: #008080;">::</span><span style="color: #007788;">Event</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
Event<span style="color: #008080;">::</span>~Event<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">Handle</span><span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>type<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">case</span> SDL_ACTIVEEVENT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>active.<span style="color: #007788;">state</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">case</span> SDL_APPMOUSEFOCUS<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span> Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>active.<span style="color: #007788;">gain</span> <span style="color: #008000;">&#41;</span>
			OnMouseFocus<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">else</span>
			OnMouseBlur<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">case</span> SDL_APPINPUTFOCUS<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span> Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>active.<span style="color: #007788;">gain</span> <span style="color: #008000;">&#41;</span>
			OnInputFocus<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">else</span>
			OnInputBlur<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">case</span> SDL_APPACTIVE<span style="color: #008080;">:</span>    <span style="color: #008000;">&#123;</span>
                    <span style="color: #0000ff;">if</span> <span style="color: #008000;">&#40;</span> Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>active.<span style="color: #007788;">gain</span> <span style="color: #008000;">&#41;</span>
			OnRestore<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">else</span>
			OnMinimize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_KEYDOWN<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnKeyDown<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>key.<span style="color: #007788;">keysym</span>.<span style="color: #007788;">sym</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>key.<span style="color: #007788;">keysym</span>.<span style="color: #007788;">mod</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>key.<span style="color: #007788;">keysym</span>.<span style="color: #007788;">unicode</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_KEYUP<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnKeyUp<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>key.<span style="color: #007788;">keysym</span>.<span style="color: #007788;">sym</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>key.<span style="color: #007788;">keysym</span>.<span style="color: #007788;">mod</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>key.<span style="color: #007788;">keysym</span>.<span style="color: #007788;">unicode</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_MOUSEMOTION<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnMouseMove<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">y</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">xrel</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">yrel</span>,<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">state</span><span style="color: #000040;">&amp;</span>SDL_BUTTON<span style="color: #008000;">&#40;</span>SDL_BUTTON_LEFT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span>,<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">state</span><span style="color: #000040;">&amp;</span>SDL_BUTTON<span style="color: #008000;">&#40;</span>SDL_BUTTON_RIGHT<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span>,<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>motion.<span style="color: #007788;">state</span><span style="color: #000040;">&amp;</span>SDL_BUTTON<span style="color: #008000;">&#40;</span>SDL_BUTTON_MIDDLE<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">!</span><span style="color: #000080;">=</span><span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_MOUSEBUTTONDOWN<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">button</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">case</span> SDL_BUTTON_LEFT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    OnLButtonDown<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">y</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">case</span> SDL_BUTTON_RIGHT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    OnRButtonDown<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">y</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">case</span> SDL_BUTTON_MIDDLE<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    OnMButtonDown<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">y</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_MOUSEBUTTONUP<span style="color: #008080;">:</span>    <span style="color: #008000;">&#123;</span>
            <span style="color: #0000ff;">switch</span><span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">button</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
                <span style="color: #0000ff;">case</span> SDL_BUTTON_LEFT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    OnLButtonUp<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">y</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">case</span> SDL_BUTTON_RIGHT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    OnRButtonUp<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">y</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
                <span style="color: #0000ff;">case</span> SDL_BUTTON_MIDDLE<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
                    OnMButtonUp<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">x</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>button.<span style="color: #007788;">y</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
                    <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
                <span style="color: #008000;">&#125;</span>
            <span style="color: #008000;">&#125;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_JOYAXISMOTION<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnJoyAxis<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jaxis.<span style="color: #007788;">which</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jaxis.<span style="color: #007788;">axis</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jaxis.<span style="color: #007788;">value</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_JOYBALLMOTION<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnJoyBall<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jball.<span style="color: #007788;">which</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jball.<span style="color: #007788;">ball</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jball.<span style="color: #007788;">xrel</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jball.<span style="color: #007788;">yrel</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_JOYHATMOTION<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnJoyHat<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jhat.<span style="color: #007788;">which</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jhat.<span style="color: #007788;">hat</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jhat.<span style="color: #007788;">value</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
        <span style="color: #0000ff;">case</span> SDL_JOYBUTTONDOWN<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnJoyButtonDown<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jbutton.<span style="color: #007788;">which</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jbutton.<span style="color: #007788;">button</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_JOYBUTTONUP<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnJoyButtonUp<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jbutton.<span style="color: #007788;">which</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>jbutton.<span style="color: #007788;">button</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_QUIT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            Exit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_SYSWMEVENT<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            <span style="color: #666666;">//Ignore</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_VIDEORESIZE<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnResize<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>resize.<span style="color: #007788;">w</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>resize.<span style="color: #007788;">h</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">case</span> SDL_VIDEOEXPOSE<span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnExpose<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        <span style="color: #0000ff;">default</span><span style="color: #008080;">:</span> <span style="color: #008000;">&#123;</span>
            OnUser<span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>user.<span style="color: #007788;">type</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>user.<span style="color: #007788;">code</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>user.<span style="color: #007788;">data1</span>,Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>user.<span style="color: #007788;">data2</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
            <span style="color: #0000ff;">break</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnInputFocus</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnInputBlur</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnKeyDown</span><span style="color: #008000;">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnKeyUp</span><span style="color: #008000;">&#40;</span>SDLKey sym, SDLMod mod, Uint16 unicode<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMouseFocus</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMouseBlur</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMouseMove</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY, <span style="color: #0000ff;">int</span> relX, <span style="color: #0000ff;">int</span> relY, <span style="color: #0000ff;">bool</span> Left,<span style="color: #0000ff;">bool</span> Right,<span style="color: #0000ff;">bool</span> Middle<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMouseWheel</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">bool</span> Up, <span style="color: #0000ff;">bool</span> Down<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnLButtonDown</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnLButtonUp</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnRButtonDown</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnRButtonUp</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMButtonDown</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMButtonUp</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> mX, <span style="color: #0000ff;">int</span> mY<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnJoyAxis</span><span style="color: #008000;">&#40;</span>Uint8 which,Uint8 axis,Sint16 value<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnJoyButtonDown</span><span style="color: #008000;">&#40;</span>Uint8 which,Uint8 button<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnJoyButtonUp</span><span style="color: #008000;">&#40;</span>Uint8 which,Uint8 button<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnJoyHat</span><span style="color: #008000;">&#40;</span>Uint8 which,Uint8 hat,Uint8 value<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnJoyBall</span><span style="color: #008000;">&#40;</span>Uint8 which,Uint8 ball,Sint16 xrel,Sint16 yrel<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnMinimize</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnRestore</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnResize</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> w,<span style="color: #0000ff;">int</span> h<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnExpose</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">Exit</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> Event<span style="color: #008080;">::</span><span style="color: #007788;">OnUser</span><span style="color: #008000;">&#40;</span>Uint8 type, <span style="color: #0000ff;">int</span> code, <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> data1, <span style="color: #0000ff;">void</span><span style="color: #000040;">*</span> data2<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Много кода, но нам надо покрыть все события SDL. В целом, мы просто берем указатель на SDL_Event, проверяем его тип и вызываем соответствующую функцию. Выглядит, что кода много, но это только потому, что много типов событий.</p>
<p>Теперь, когда с этим разобрались, перейдет к <strong>App.h</strong> и подключим наш новый класс:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;Event.h&quot;</span>
<span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Event <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>            Running<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Screen<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Test<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Evt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Все должно хорошо скомпилироваться. Теперь надо связать поступающие события с нашим классом. Найдите App::Event() и измените функцию вот так:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Event</span><span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Evt<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Event<span style="color: #008080;">::</span><span style="color: #007788;">Handle</span><span style="color: #008000;">&#40;</span>Evt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Мы передаем событие в наш класса, теперь он будет заботиться о правильном вызовов функций. Теперь, когда мы хотим использовать событие, мы должны переопределить функцию. Так как мы избавились от проверки события SDL_Quit, давайте использовать вместо этого метод класса. Откройте <strong>App.h</strong>, и добавьте следующие функции:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #339900;">#include &quot;Event.h&quot;</span>
<span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008080;">:</span> <span style="color: #0000ff;">public</span> Event <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>            Running<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Screen<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Test<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Evt<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Exit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Функция Exit() будет обрабатывать событие SDL_Quit. У нас есть прототип, позволяющий определить, что он делает, теперь добавим реализацию. Откройте <strong>App.cpp</strong> и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Exit</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Перекомпилируйте и попробуйте запустить. Программа должна закрываться по крестику как и раньше. Я рекомендую вам ознакомиться с несколькими другими событиями. В дальнейшем мы будем использовать некоторые из них в нашей игре.</p>
<p>Перейти на более чем на следующем уроке, чтобы взглянуть на создание нашей первой игре, крестики-нолики./strong</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/sdl-tutorial-3-events/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/sdl-tutorial-3-events/</feedburner:origLink></item>
		<item>
		<title>SDL: Как создать игру. Координаты и блиттинг.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/QFEFhQv7fL8/</link>
		<comments>http://www.charnad.com/blog/sdl-tutorial-2-coordinates-and-blitting/#comments</comments>
		<pubDate>Tue, 01 May 2012 16:20:25 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[blitting]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1380</guid>
		<description><![CDATA[Это вольный перевод и переосмысление статьи, SDL Coordinates and Bliting за авторством Tim Jones. Готовый код я буду выкладывать на Github, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы. Используя первую [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="SDL" />Это вольный перевод и переосмысление статьи, <a href="http://www.sdltutorials.com/sdl-coordinates-and-blitting">SDL Coordinates and Bliting</a> за авторством Tim Jones. Готовый код я буду выкладывать на <a href="https://github.com/charnad/SDLTutorial">Github</a>, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь: вы можете оставить комментарий или написать мне на почту, она указана внизу страницы.</p>
<p>Используя <a href="http://www.charnad.com/blog/sdl-tutorial-1-basics/">первую статью</a>, как базу, углубимся в мир поверхностей SDL. Я пытался донести до вас мысль, что SDL поверхности - это в основном изображения, хранящиеся в памяти. Представьте что, у нас есть пустая поверхность размером 320x240 пикселей. Если добавить к ней систему SDL координат, то получится что-то вроде этого:</p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/2/coords.jpg"><br />
Эта система координат отличается, от обычной. Обратите внимание, что координата Y увеличивается вниз, а координата X увеличивается вправо. Это важно понимать, чтобы правильно рисовать изображения на экране.<span id="more-1380"></span></p>
<p>Поскольку у нас уже есть основная поверхность (Screen), нам нужен способ, чтобы рисовать на ней. Этот процесс называется блиттинг [<i>Blitting - Перенос битовых блоков</i>], когда мы в общем переносим одно изображение на другое. Но прежде чем мы сможем это сделать, мы должны загрузить эти изображения в память. SDL предлагает простую функцию для этого - SDL_LoadBMP. Примерный код может выглядеть следующим образом:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">SDL_Surface<span style="color: #000040;">*</span> TmpSurface<span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>TmpSurface <span style="color: #000080;">=</span> SDL_LoadBMP<span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;mypicture.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #666666;">//Error!</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Все довольно просто, SDL_LoadBMP принимает один аргумент, имя файла, который вы хотите загрузить, и возвращает поверхность.  Если функция возвращает NULL, то либо файл не найден, либо поврежден или произошла какая-либо другая ошибка. К сожалению, чтобы все работало быстро, одного этого метода недостаточно. Часто изображение будет загружено в другом формате. И, когда мы будем отображать изображение на экране, мы можем столкнуться с потерей производительности, выпадением цветов изображения, и т.п. Но, к счастью SDL предлагает решение этой проблемы - функцию SDL_DisplayFormat. Она принимает уже загруженную поверхность, и возвращает новую, уже использующую тот же формат, что и дисплей. </p>
<p>Давайте этот процесс завернем класс. Возьмем код из предыдущей статьи за основу и добавим два новых файла: <strong>Sprite.h</strong> и <strong>Sprite.cpp</strong>. Откройте <strong>Sprite.h</strong> и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _SPRITE_H_</span>
<span style="color: #339900;">#define _SPRITE_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Sprite <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Sprite<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">static</span> SDL_Surface<span style="color: #000040;">*</span> Load<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Мы создали простую статическую функцию Load, которая будет загружать файл в поверхность. Теперь откроем <strong>Sprite.cpp</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Sprite</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
SDL_Surface<span style="color: #000040;">*</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    SDL_Surface<span style="color: #000040;">*</span> Temp <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    SDL_Surface<span style="color: #000040;">*</span> Result <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Temp <span style="color: #000080;">=</span> SDL_LoadBMP<span style="color: #008000;">&#40;</span>File<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Result <span style="color: #000080;">=</span> SDL_DisplayFormat<span style="color: #008000;">&#40;</span>Temp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>Temp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> Result<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Надо отменить несколько важных вещей. Во-первых, всегда помните, что когда вы создаете указатель, установите его в значение NULL или 0.  Вы можете столкнуться с проблемами, если вы это не сделаете. Во-вторых, обратите внимание, что SDL_DisplayFormat возвращает новую поверхность, а не перезаписывает оригинальную. Это важно помнить, потому что, поскольку он создает новую поверхность, мы должны освободить старую. В противном случае, у она так и будет занимать память.</p>
<p>Теперь у нас есть способ загрузки поверхностей в памяти, теперь же нужен способ отображать их поверх других поверхностей. Как и в случае с загрузкой изображений, SDL предлагает функцию для блиттинга: SDL_BlitSurface. Она не такая простая как SDL_LoadBMP, но все же достаточно простая. Откроем <strong>Sprite.h</strong> и добавим следующие прототипы функций:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _SPRITE_H_</span>
<span style="color: #339900;">#define _SPRITE_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Sprite <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Sprite<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">static</span> SDL_Surface<span style="color: #000040;">*</span> Load<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> Draw<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Теперь откройте <strong>Sprite.cpp</strong>, и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Sprite</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
SDL_Surface<span style="color: #000040;">*</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    SDL_Surface<span style="color: #000040;">*</span> Temp <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    SDL_Surface<span style="color: #000040;">*</span> Result <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Temp <span style="color: #000080;">=</span> SDL_LoadBMP<span style="color: #008000;">&#40;</span>File<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Result <span style="color: #000080;">=</span> SDL_DisplayFormat<span style="color: #008000;">&#40;</span>Temp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>Temp<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> Result<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dest <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span> <span style="color: #000040;">||</span> Src <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    SDL_Rect Area<span style="color: #008080;">;</span>
    Area.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> X<span style="color: #008080;">;</span>
    Area.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> Y<span style="color: #008080;">;</span>
&nbsp;
    SDL_BlitSurface<span style="color: #008000;">&#40;</span>Src, <span style="color: #0000ff;">NULL</span>, Dest, <span style="color: #000040;">&amp;</span>Area<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Прежде всего, посмотрим на аргументы, которые передаются функции Draw. У нас есть две поверхности, и две переменные типа int. Первая поверхность Dest - на ней мы будем рисовавать, вторая поверхность Src - из нее будут браться данные для отображения. Можно сказать, что мы "наклеиваем" (помните аналогию со стикерами?) Src на Dest. X, Y - это координаты на поверхности Dest где будет находиться верхний левый угол изображения из Src. </p>
<p>Теперь к содержимому функции. Сначала мы проверяем, что у нас есть действительная поверхность, иначе возвращаем false. Далее, определяем SDL_Rect. Это SDL структура, которая состоит из четырех элементов: X, Y, W, H.  Как вы, возможно, догадались, это задает размеры прямоугольника. В нашем случае, мы заботимся только о том, где мы рисуем, а не сколько. Поэтому, мы назначаем X, Y координаты на поверхности Dest. Если вам интересно, что означает NULL среди параметров функции SDL_BlitSurface, то это еще один параметр SDL_Rect. К нему мы вернемся позже. Наконец, мы вызваем функцию переноса изображения, и возвращаем true. </p>
<p>Теперь, чтобы убедиться, что все это работает, давайте создадим тестовую поверхность. Откройте <strong>App.h</strong>, и создайте новую поверхность, и подключите недавно созданный <strong>Sprite.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
<span style="color: #339900;">#include &quot;Sprite.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>            Running<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Screen<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Test<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Не забудьте инициализировать поверхность значением NULL в конструкторе:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">App<span style="color: #008080;">::</span><span style="color: #007788;">App</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Test <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    Screen <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>И так же не забудьте "прибраться" за собой:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Cleanup</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>Test<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_FreeSurface<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_Quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Давайте теперь загрузим изображение. Перейдите к функции App::Init(), добавьте код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">&nbsp;
<span style="color: #0000ff;">bool</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SDL_Init<span style="color: #008000;">&#40;</span>SDL_INIT_EVERYTHING<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&lt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Screen <span style="color: #000080;">=</span> SDL_SetVideoMode<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">640</span>, <span style="color: #0000dd;">480</span>, <span style="color: #0000dd;">32</span>, SDL_HWSURFACE <span style="color: #000040;">|</span> SDL_DOUBLEBUF<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Test <span style="color: #000080;">=</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Load</span><span style="color: #008000;">&#40;</span><span style="color: #FF0000;">&quot;image.bmp&quot;</span><span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Не забудьте заменить "image.bmp" реальным изображением, которое у вас есть. Если нету - откройте MSPaint, что-нибудь нарисуйте, и сохраните в той же папке, где будет ваш исполняемый файл. Теперь у нас есть загруженное изображение, которое можно нарисовать. Найдите App::Render и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, Test, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    SDL_Flip<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Обратите внимание на новую функцию SDL_Flip. Это просто обновление буфера и вывод Screen на экран. Это называется двойной буферизацией. Это процесс рисования всего в памяти, и, потом вывод на экран. Если этого не делать, получилось бы мерцающее изображение. Помните флаг SDL_DOUBLEBUF? Это он и включает двойную буферизацию. </p>
<p>Скомпилируйте код и убедитесь, что все работает правильно. Вы должны увидеть изображение в верхнем левом углу экрана.  Если да, то поздравляю, вы на один шаг ближе к самой игре. Если нет, убедитесь, что ваш image.bmp находится в той же папке, что и исполняемый файл. Кроме того, убедитесь, что это действительно bitmap файл.</p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/2/ss1.jpg"></p>
<p>Теперь давайте продвинемся немного дальше. Хотя это круто уметь рисовать изображение на экране, часто нам нужна только его часть. Возьмем, к примеру, набор тайлов (tileset):</p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/2/tileset.png"></p>
<p>Хотя это одно изображение, мы хотим нарисовать отдельную его часть.  Открытие еще раз <strong>Sprite.h</strong> и добавьте следующий код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _SPRITE_H_</span>
<span style="color: #339900;">#define _SPRITE_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> Sprite <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        Sprite<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
        <span style="color: #0000ff;">static</span> SDL_Surface<span style="color: #000040;">*</span> Load<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> File<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> Draw<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">bool</span> Draw<span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y, <span style="color: #0000ff;">int</span> X2, <span style="color: #0000ff;">int</span> Y2, <span style="color: #0000ff;">int</span> W, <span style="color: #0000ff;">int</span> H<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Теперь в <strong>Sprite.cpp</strong><span style="color: red;"> (Внимание, мы добавляем еще одну функцию Draw, мы не заменяем первую)</span>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>SDL_Surface<span style="color: #000040;">*</span> Dest, SDL_Surface<span style="color: #000040;">*</span> Src, <span style="color: #0000ff;">int</span> X, <span style="color: #0000ff;">int</span> Y, <span style="color: #0000ff;">int</span> X2, <span style="color: #0000ff;">int</span> Y2, <span style="color: #0000ff;">int</span> W, <span style="color: #0000ff;">int</span> H<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Dest <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span> <span style="color: #000040;">||</span> Src <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    SDL_Rect DestArea<span style="color: #008080;">;</span>
&nbsp;
    DestArea.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> X<span style="color: #008080;">;</span>
    DestArea.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> Y<span style="color: #008080;">;</span>
&nbsp;
    SDL_Rect SrcArea<span style="color: #008080;">;</span>
&nbsp;
    SrcArea.<span style="color: #007788;">x</span> <span style="color: #000080;">=</span> X2<span style="color: #008080;">;</span>
    SrcArea.<span style="color: #007788;">y</span> <span style="color: #000080;">=</span> Y2<span style="color: #008080;">;</span>
    SrcArea.<span style="color: #007788;">w</span> <span style="color: #000080;">=</span> W<span style="color: #008080;">;</span>
    SrcArea.<span style="color: #007788;">h</span> <span style="color: #000080;">=</span> H<span style="color: #008080;">;</span>
&nbsp;
    SDL_BlitSurface<span style="color: #008000;">&#40;</span>Src, <span style="color: #000040;">&amp;</span>SrcArea, Dest, <span style="color: #000040;">&amp;</span>DestArea<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Обратите внимание, что это в основном точно такая же функция, как и первыая, за исключением того, мы добавили еще один SDL_Rect. Этот SDL_Rect прямоугольник определяет, какие пикселы из исходного изображения скопировать в итоговое. Если, например, указаны параметры 0, 0, 50, 50, то отрисовано было бы лишь левая верхняя часть поверхности (квадрат размером 50х50).</p>
<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/2/draw2.jpg"></p>
<p>Давайте проверим как это работает, найдите App::Render(), и добавьте следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, Test, <span style="color: #0000dd;">0</span>, <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Sprite<span style="color: #008080;">::</span><span style="color: #007788;">Draw</span><span style="color: #008000;">&#40;</span>Screen, Test, <span style="color: #0000dd;">70</span>, <span style="color: #0000dd;">110</span>, <span style="color: #0000dd;">90</span>, <span style="color: #0000dd;">90</span>, <span style="color: #0000dd;">50</span>, <span style="color: #0000dd;">50</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    SDL_Flip<span style="color: #008000;">&#40;</span>Screen<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl-tutorials/2/ss2.jpg"></p>
<p>Должно получиться, что ваше изображение отображается по координатам 70, 110 и видна только его часть. Надо обратить особое внимание на то, как эти функции работают, и как устроена система SDL координат, мы будем еще не раз это использовать. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/sdl-tutorial-2-coordinates-and-blitting/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/sdl-tutorial-2-coordinates-and-blitting/</feedburner:origLink></item>
		<item>
		<title>SDL: Как создать игру. Базовое окно.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/NjT80d5mRF4/</link>
		<comments>http://www.charnad.com/blog/sdl-tutorial-1-basics/#comments</comments>
		<pubDate>Tue, 01 May 2012 10:23:59 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[code::blocks]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1357</guid>
		<description><![CDATA[Это вольный перевод и переосмысление статьи, SDL Tutorial Basic за авторством Tim Jones. Хочу выделить, что это не прямой перевод, код не полностью повторяет код оригинала, тем не менее вы можете сверяться и сравнивать с оригинальной статьей. Готовый код я буду выкладывать на Github, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="SDL" />Это вольный перевод и переосмысление статьи, <a href="http://www.sdltutorials.com/sdl-tutorial-basics">SDL Tutorial Basic</a> за авторством Tim Jones. Хочу выделить, что это не прямой перевод, код не полностью повторяет код оригинала, тем не менее вы можете сверяться и сравнивать с оригинальной статьей. Готовый код я буду выкладывать на <a href="https://github.com/charnad/SDLTutorial">Github</a>, откуда вы сможете скачать так же ZIP-архив. Если вы увидите ошибку, неточность, или у вас возникнут проблемы - обращайтесь. Вы можете оставить комментарий или написать мне на почту, она указана внизу страницы. Итак начнем.</p>
<p>Эти обучающие статьи предназначены для тех, у кого уже есть опыт использования C++ или другого языка программирования. Если у вас возникают сложности с пониманием кода, а не концепций, то я настоятельно советую вам сначала прочитать статью, объясняющую основы языка С++. Необязательно знать все о С++, но чем больше - тем проще вам будет в дальнейшем.</p>
<p>В статьях я буду использовать Code::Blocks в качестве IDE и gcc с mingw для компиляции. [Я лично изначально использовал gcc с cygwin, но такой набор потребует включения cygwin1.dll в дистрибутив, что может накладывать лицензионные ограничения. Поэтому позже я установил mingw компилятор из тех же репозиториев cygwin.] Если вы хотите использовать другую IDE и/или компилятор, вы, конечно, можете это сделать, если достаточно уверены, что сможете включить все библиотеки в линковку. Скачать же Code::Blocks можно на официальном сайте <a href="http://www.codeblocks.org/downloads/26">http://www.codeblocks.org</a> (скачать версию, включающую MinGW). Рекомендуется использовать стабильную версию, если вы не хотите тратить время на ночные сборки.</p>
<p>Эти статьи в значительной степени сосредоточены вокруг SDL (Simple DirectMedia Layer), 2D кросс-платформенной графической библиотеки. Эта библиотека позволит отрисовывать графику, и делать разные классные вещи, которые потом и помогут нам сделать игру. Вам также надо будет загрузить библиотеку с сайта <a href="http://www.libsdl.org/download-1.2.php">http://www.libsdl.org</a>. Вам нужен tar-файл в разделе "Development Libraries, Win32" и zip-файл в разделе "Runtime Libraries, Win32". Если вы используете Visual Studio - выберите соответствующий файл вместо MinGW версии. После скачивания вы можете скопировать .dll файлы в папку Windows/system32, таким образом любое SDL приложение сможет его использовать. [Я не стал этого делать, достаточно чтобы SDL.dll и другие необходимые dll файлы находились в той же папке, что и исполняемый файл]. <span id="more-1357"></span></p>
<p>Начните новый проект (Blank project) в Code::Blocks, назовите по желанию и сохраните в удобное для вас место. Откройте tar-файл (который вы скачали из раздела "Development Libraries"), из него нам нужны папки include и lib, распакуйте их в папку вашего проекта. Вернемся обратно в Code::Blocks, кликните правой кнопкой на проект, слева в списке проектов, и в появившемся меню выберите "Build Options". Слева в дереве скорее всего будет имя вашего проекта и два пункта: Debug и Release. Выберите корень дерева, таким образом мы установим настройки сразу для всего проекта. Нас интересуют две вкладки: Search Directories и Linker Settings. В Search Directories по умолчанию выбрана вкладка Compiler, снизу нажмите Add и добавьте 2 папки: include и include/SDL. Этим мы облегчили подключение заголовочных файлов. Теперь во вкладке Linker Settings также нажимаем Add и добавляем файлы: libSDLmain.a и libSDL.dll.a (!Именно в таком порядке!). Этим мы подключили библиотеки SDL в наш проект. Нажимайте ОК и настройка проекта на этом закончена. [<i>Если в будущем у вас возникнут проблемы с '_WinMain@16', то в Linker Settings, справа от библиотек в окне Other linker options допишите -lmingw32. Если возникнет проблема с libgcc_s_dw2-1.dll, допишите там же -static.</i>]</p>
<p>Давайте, наконец, создадим два файла, назовем их <strong>App.h</strong> и <strong>App.cpp</strong>, это будет ядром нашей программы. Откройте <strong>App.h</strong> и добавьте туда следующий код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Теперь в файл <strong>App.cpp</strong> добавим вот этот код:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;App.h&quot;</span>
&nbsp;
App<span style="color: #008080;">::</span><span style="color: #007788;">App</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Execute</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    App App<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> App.<span style="color: #007788;">Execute</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Класс App - это основа всей нашей программы. Давайте сделаем шаг в сторону и я расскажу как игры обычно устроены. Большинство игр состоят из 5 функций, контролирующих игровой процесс. Обычно это:</p>
<p>Initialize<br />
Функция обрабатывает загрузку всех данных, текстур, карт, NPC, чего угодно.</p>
<p>Event<br />
Функция обрабатывает все поступающие события от мышки, клавиатуры, джойстика и других устройств.</p>
<p>Loop<br />
Функция обрабатывает обновление данных, например движение NPC по экрану, уменьшение здоровье персонажа и так далее.</p>
<p>Render<br />
Функция занимается отображением всего на экране. Она НЕ обрабатывает манипуляции с данными - этим занимается Loop.</p>
<p>Cleanup<br />
Функция просто отключает все использующиеся ресурсы и закрывает игру.</p>
<p>Важно понимать, что игра это просто один большой цикл. Внутри этого цикла случаются события, обновляются данные, рисуются картинки. Поэтому базовая структура игры может иметь следующий вид:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">Initialize<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span><span style="color: #0000ff;">true</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Events<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>На каждом шаге цикла мы что-то делаем с данными и соответствующе их отображаем. События используются для манипуляции данными пользователем. Они в целом не являются необходимыми чтобы создать игру, но нужны, для возможности управлять игровым процессом.</p>
<p>Поясним эту мысль на примере. Например, у нас есть наш рыцарь, герой игры. Все, что мы хотим сделать, это просто его перемещать. Если я нажимать влево - он идет налево. Сейчас мы выясним, как это сделать в цикле. Во-первых, мы знаем, что мы хотим, проверять события (события клавиатуры). Так как события нужны для управления данными, нам нужны будут переменные, которые будут изменяться. Тогда мы можем использовать эти переменные для отображения нашего рыцаря на экране. У нас могло бы быть что-нибудь навроде:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Key <span style="color: #000080;">==</span> LEFT<span style="color: #008000;">&#41;</span> X<span style="color: #000040;">--</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Key <span style="color: #000080;">==</span> RIGHT<span style="color: #008000;">&#41;</span> X<span style="color: #000040;">++</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Key <span style="color: #000080;">==</span> UP<span style="color: #008000;">&#41;</span> Y<span style="color: #000040;">--</span><span style="color: #008080;">;</span>
<span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Key <span style="color: #000080;">==</span> DOWN<span style="color: #008000;">&#41;</span> Y<span style="color: #000040;">++</span><span style="color: #008080;">;</span>
&nbsp;
RenderImage<span style="color: #008000;">&#40;</span>KnightImage, X, Y<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span></pre></td></tr></table></div>

<p>Это работает, потому что каждый цикл проверяется, нажата ли кнопка ВЛЕВО, ВПРАВО и т.д., и если да, то уменьшить или увеличить переменную. Так что, если наша игра идет со скоростью 30 кадров в секунду и мы нажимаем НАЛЕВО, то рыцарь будет двигаться влево со скоростью 30 пикселей в секунду. Если вам еще не удалось разобраться в принципе игрового цикла, то вы скоро с этим справитесь. Цикл необходим, чтобы игра правильно функционировала.</p>
<p>Возвращаясь к нашему концептуальному коду (5 функций), мы можем добавить эти дополнительные функции в наш проект, в файле <strong>App.h</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>    Running<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>А в файле <strong>App.cpp</strong>:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;App.h&quot;</span>
&nbsp;
App<span style="color: #008080;">::</span><span style="color: #007788;">App</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">bool</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Execute</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">false</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #000040;">-</span><span style="color: #0000dd;">1</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    SDL_Event Event<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>Running<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>SDL_PollEvent<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>Event<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
            Event<span style="color: #008000;">&#40;</span><span style="color: #000040;">&amp;</span>Event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #008000;">&#125;</span>
&nbsp;
        Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">*</span> argv<span style="color: #008000;">&#91;</span><span style="color: #008000;">&#93;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    App App<span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> App.<span style="color: #007788;">Execute</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Event</span><span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Loop</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Render</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Cleanup</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span><span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Вы видите несколько новых переменных, но давайте сначала разберемся что же делает этот код. Во-первых, мы пытаемся инициализировать нашу игру, если не вышло - мы возвращаем -1 (код ошибки), тем самым закрывая программу. Если все хорошо, то мы входим в игровой цикл. В цикла мы используем SDL_PollEvent для проверки событий и передаем их по одному в Event. После этого, мы идем в Loop для перемещения данных вокруг, и всего в таком роде, а затем отображаем нашу игру. Повторяем это бесконечно. Если пользователь выходит из игры, мы попадаем в Cleanup, которая освободит используемые ресурсы. Вот так, достаточно просто.</p>
<p>Теперь, давайте посмотрим на SDL_Event и SDL_PollEvent. Первое - это структура, которая содержит информацию о событиях. Вторая функция, которая будет захватывать любые события, ожидающие в очереди. Очередь может состоять из любого количества событий, поэтому мы должны перебрать их по очереди. Например, позволяет нажимает кнопку А и перемещает мышь, в тот момент, когда исполняется Render(). SDL обнаружит это и поставит два события в очередь, по одному на каждое нажатие клавиши и перемещение мыши. Мы получаем эти события из очереди с помощью SDL_PollEvent, а затем передаем его в Event, чтобы обработать соответствующим образом. Когда в очереди нет событий, SDL_PollEvent вернет false, выйдя из цикла обработки событий.</p>
<p>Другая добавленная переменная Running - это наш выход из цикла игры. Если оно false, значит игра закончилась, и надо выйти из программы. Так что, если, например, если пользователь нажимает клавишу ESC мы можем присвоить ей false, и тем самым выйти из игры.</p>
<p>На данном этапе программа должна компилироваться без проблем, правда, вы можете заметить, что ее нельзя закрыть. Даже, вероятно, придется использовать диспетчер задач для завершения программы.</p>
<p>Теперь, когда все настроено, давайте создадим окно, где будет отрисовываться наша игра. Откройте <strong>App.h</strong> и добавить переменную поверхности SDL:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _APP_H_</span>
<span style="color: #339900;">#define _APP_H_</span>
&nbsp;
<span style="color: #339900;">#include &lt;SDL.h&gt;</span>
&nbsp;
<span style="color: #0000ff;">class</span> App <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">private</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span>    Running<span style="color: #008080;">;</span>
        SDL_Surface<span style="color: #000040;">*</span>    Screen<span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        App<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">int</span> Execute<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">public</span><span style="color: #008080;">:</span>
        <span style="color: #0000ff;">bool</span> Init<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Event<span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Loop<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Render<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
        <span style="color: #0000ff;">void</span> Cleanup<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span><span style="color: #008080;">;</span>
&nbsp;
<span style="color: #339900;">#endif</span></pre></td></tr></table></div>

<p>Думаю, самое время объяснить что такое SDL поверхность. SDL поверхность это все, что можно нарисовать, и все на чем можно нарисовать. Например, у нас есть лист бумаги, карандаш, и стикеры. Бумаги можно назвать поверхностью. Мы можем рисовать на ней, наклеивать стикеры и прочее. Стикеры тоже можно считать поверхностями, мы можем рисовать и на них, и наклеивать другие стикеры поверх. Таким что, Screen - это просто наш "лист бумаги", на котором мы будем рисовать.</p>
<p>Теперь, давайте отредактируем функцию Init, чтобы инициализировать эту поверхность:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">bool</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Init</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>SDL_Init<span style="color: #008000;">&#40;</span>SDL_INIT_EVERYTHING<span style="color: #008000;">&#41;</span> <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#40;</span>Screen <span style="color: #000080;">=</span> SDL_SetVideoMode<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">640</span>, <span style="color: #0000dd;">480</span>, <span style="color: #0000dd;">32</span>, SDL_HWSURFACE <span style="color: #000040;">|</span> SDL_DOUBLEBUF<span style="color: #008000;">&#41;</span><span style="color: #008000;">&#41;</span> <span style="color: #000080;">==</span> <span style="color: #0000ff;">NULL</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Первое, что нужно сделать, это запустить собственно SDL, чтобы мы могли получить доступ к его функциям. Мы командуем SDL инициализировать все, что доступно; есть различные параметры, которые можно передать, но это на данный момент это не важно. Следующая функция: SDL_SetVideoMode. Она и создаст наше окно и поверхность. Она принимает 4 параметра: ширину окна, высота окна, битовое разрешение (рекомендуется 16 или 32), и различные флаги отображения. Есть довольно много флагов, но тех, которые мы используем, достаточно на данный момент. Первый флаг говорит SDL использовать аппаратную памяти для хранения изображений, а второй говорит SDL использовать двойную буферизацию (это предотвратит мерцание на экране). Еще один флаг, который может заинтересовать вас - это SDL_FULLSCREEN, он запускает приложение в полноэкранном режиме.</p>
<p>Теперь, когда окно настроено, давайте сделаем так, чтобы все работало гладко. Изменим функцию App::Cleanup() и добавим следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Cleanup</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    SDL_Quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Мы просто выходим из SDL. Надо учесть, что в этой функции, мы будем освобождать использованные поверхности</p>
<p>Чтобы все было аккуратно, надо также инициализировать указатель Screen значением NULL, в конструкторе класса. В <strong>App.cpp</strong> добавить следующее:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;">App<span style="color: #008080;">::</span><span style="color: #007788;">App</span><span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    Screen <span style="color: #000080;">=</span> <span style="color: #0000ff;">NULL</span><span style="color: #008080;">;</span>
    Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">true</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>Попробуйте скомпилировать проект, посмотрите как он работает. Должно появится пустое окно. Его все еще нельзя закрыть просто так, придется воспользоваться диспетчером задач. Это не очень удобно, поэтому давайте исправим ситуацию. Изменим функцию Event:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">void</span> App<span style="color: #008080;">::</span><span style="color: #007788;">Event</span><span style="color: #008000;">&#40;</span>SDL_Event<span style="color: #000040;">*</span> Event<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">if</span><span style="color: #008000;">&#40;</span>Event<span style="color: #000040;">-</span><span style="color: #000080;">&gt;</span>type <span style="color: #000080;">==</span> SDL_QUIT<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
        Running <span style="color: #000080;">=</span> <span style="color: #0000ff;">false</span><span style="color: #008080;">;</span>
    <span style="color: #008000;">&#125;</span>
<span style="color: #008000;">&#125;</span></pre></td></tr></table></div>

<p>SDL события различаются по типу. Эти типы могут варьироваться от нажатия клавиш, движения мыши, все что нам нужно это проверить его тип. Нужный нам тип - это запрос на закрытие окна (например, когда пользователь нажимает кнопку X). Если это событие произойдет, мы устанавливаем Running = false, тем самым завершив нашу программу. Достаточно просто. Мы рассмотрим больше событий в других статьях.</p>
<p>Если вы хорошо разобрались и понимаете, как работает код в этой статье, вы можете перейти к следующей, чтобы узнать больше о поверхности SDL.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/sdl-tutorial-1-basics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/sdl-tutorial-1-basics/</feedburner:origLink></item>
		<item>
		<title>Настройка SDL + NetBeans CDT</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/Me0zpaOnJCg/</link>
		<comments>http://www.charnad.com/blog/netbeans-cdt-setup-for-sdl/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 12:03:28 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[netbeans]]></category>
		<category><![CDATA[sdl]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1284</guid>
		<description><![CDATA[Я уже писал о написании игр с помощью SDL на Python (pygame), хотя, до продолжения у меня руки не дошли, к сожалению. Тем не менее, я так же хочу написать, как я подключал SDL библиотеку для разработки на С++ в моей разлюбимой IDE NetBeans. Причины для выбора NetBeans довольно забавные: у меня не хватало места [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/sdl_logo.png" alt="" />Я уже писал о написании игр с помощью SDL на Python (pygame), хотя, до продолжения у меня руки не дошли, к сожалению. Тем не менее, я так же хочу написать, как я подключал SDL библиотеку для разработки на С++ в моей разлюбимой IDE NetBeans. Причины для выбора NetBeans довольно забавные: у меня не хватало места на диске для установки Visual Studio, а NetBeans уже был и с ним я неплохо знаком. Сначала я думал, что достаточно будет скачать CDT (С Developer Tools) и вперед, но все не так просто оказалось.</p>
<p><span id="more-1284"></span></p>
<p>В качестве компилятора можно испорльзовать GCC и G++. Есть 2 пакета, откуда его можно получить: Cygwin и MinGW. Свою эпопею я начал с MinGW, но проблема в том, что make в MinGW не поддерживается NetBeans, и надо будет доустанавливать MSYS, которая находится на том же сайте. Кроме того внутренний терминал NetBeans будет работать только с Cygwin. Поэтому в итоге я пришел к тому, что у меня стоит Cygwin.</p>
<p>Устанавливайте <a href="http://www.cygwin.com/">Cygwin</a> в папку без пробелов, если вы большой любитель порядка и хотите его всенепременно в Program Files - сделайте символическую ссылку C:/cygwin -> C:/Program Files/Cygwin, как это сделал я. При установке выберите gcc, g++, gdb, make и все, что он вам еще предложит, не откладывайте инсталлер далеко, вероятно, придется доустановить библиотеки libintl-3, libintl-8, libiconv, libncursesw. Не могу точно сказать что он сделает автоматически, потому как на момент установки у меня уже было скачано несколько библиотек вручную. </p>
<p>После установки Cygwin в NetBeans открывайте Tools -> Options -> C/C++, на первой вкладке Build Tools нажимайте Add и указывайте путь к папке C:/cygwin/bin, откуда NetBeans должен подцепить компиляторы и подставить их в нужные поля. </p>
<p>На этом настройка IDE закончена, вы можете создать C++ проект (обратите внимание, вы создаете C/C++ проект, выбор между собственно C и C++ происходит в маленьком выпадающем меню справа, рядом со строкой Create Main File. Если у вас будет С проект, и вы, например заинклюдите <iostream>, компилятор будет ругаться, что нет такого файла.</p>
<p>Время настроить SDL. С <a href="http://www.libsdl.org/">сайта</a> скачиваем <a href="http://www.libsdl.org/release/SDL-devel-1.2.14-mingw32.tar.gz">SDL-devel-1.2.14-mingw32.tar.gz</a>. Оттуда копируем в наш проект папку lib, include, а из папки bin кладем SDL.dll в корень проекта. Далее идем в свойства проекта:<br />
1. Build -> C++ Compiler -> General -> Include Directories и добавляем папку include/SDl, а так<br />
же укажем -O3 в Additional Options.<br />
2. Build -> Linker -> Additional Library Directories указываем папку lib, в Libraries добавляем файлы (Add Library File) libSDLmain.dll.a, libSDLmain.a в этом же порядке. Если мы нажмем Additional Options, то увидим там в конце строку "-LSDL SDL/libSDLmain.a SDL/libSDL.dll.a", что есть хорошо.</p>
<p>Наконец, в main.cpp можно написать:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#include &quot;include/SDL/SDL.h&quot;</span>
&nbsp;
<span style="color: #0000ff;">int</span> main<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">int</span> argc, <span style="color: #0000ff;">char</span><span style="color: #000040;">**</span> argv<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
&nbsp;
    SDL_Init<span style="color: #008000;">&#40;</span>SDL_INIT_EVERYTHING<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_SetVideoMode<span style="color: #008000;">&#40;</span><span style="color: #0000dd;">640</span>, <span style="color: #0000dd;">480</span>, <span style="color: #0000dd;">0</span>, SDL_HWSURFACE <span style="color: #000040;">|</span> SDL_DOUBLEBUF<span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    SDL_Quit<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
&nbsp;
    <span style="color: #0000ff;">return</span> <span style="color: #0000dd;">0</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>Теперь можно нажать кнопку RUN и увидеть быстро моргнувшее окно SDL и надпись RUN SUCCESSFUL (total time: 326ms). Успех.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/netbeans-cdt-setup-for-sdl/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/netbeans-cdt-setup-for-sdl/</feedburner:origLink></item>
		<item>
		<title>Symfony: как добавить свой экшен в DoctrineRouteCollection</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/OoFNFspyJhU/</link>
		<comments>http://www.charnad.com/blog/symfony-custom-action-with-doctrineroutecollectio/#comments</comments>
		<pubDate>Mon, 04 Jul 2011 11:28:56 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1273</guid>
		<description><![CDATA[Я часто сталкивался с необходимостью указать путь к своему экшену, например в link_to. До какого-то времени для меня вполне работал вариант 'module/action?parameter=value'. Однако, в один прекрасный день, количество таких ссылок возросло до нескольких сотен на странице. И они порядком тормозили, потому что роутингу приходилось проверять все указанные роуты, перед тем как использовать default. Решением в [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />Я часто сталкивался с необходимостью указать путь к своему экшену, например в link_to. До какого-то времени для меня вполне работал вариант 'module/action?parameter=value'. Однако, в один прекрасный день, количество таких ссылок возросло до нескольких сотен на странице. И они порядком тормозили, потому что роутингу приходилось проверять все указанные роуты, перед тем как использовать default. Решением в таких случаях являются именованные роуты, например '@users'. Но вот вопрос, как сделать именованный роут для админ генеренного модуля. Для таких модулей, добавляется DoctrineRouteCollection роут, который на самом деле генерит 7 роутов module_new, module_list и т.д.</p>
<p>Ну и вот мы делаем такой финт ушами:</p>

<div class="wp_syntax"><div class="code"><pre class="yaml" style="font-family:monospace;"><span style="color: #007F45;">modules</span>:<span style="color: green;">
  class</span><span style="font-weight: bold; color: brown;">: </span>sfDoctrineRouteCollection<span style="color: #007F45;">
  options</span>:<span style="color: green;">
    model</span><span style="font-weight: bold; color: brown;">: </span>               modules<span style="color: green;">
    module</span><span style="font-weight: bold; color: brown;">: </span>              modules<span style="color: green;">
    prefix_path</span><span style="font-weight: bold; color: brown;">: </span>         /modules<span style="color: green;">
    column</span><span style="font-weight: bold; color: brown;">: </span>              module_id<span style="color: green;">
    with_wildcard_routes</span><span style="font-weight: bold; color: brown;">: </span>true<span style="color: green;">
    object_actions</span><span style="font-weight: bold; color: brown;">: </span>      <span class="br0">&#123;</span> action1<span style="font-weight: bold; color: brown;">: </span>GET, action2<span style="font-weight: bold; color: brown;">: </span>GET <span class="br0">&#125;</span><span style="color: #007F45;">
  requirements</span>:<span style="color: green;">
    module_id</span><span style="font-weight: bold; color: brown;">: </span>       \d+</pre></div></div>

<p>В сгенеренный роут я добавил параметр object_action, после чего этот роут будет так же генерить роуты @modules_action1 и @modules_action2, что нам собственно и нужно. А GET - это тип запроса, на который будет отзываться новоделанный роут.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-custom-action-with-doctrineroutecollectio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-custom-action-with-doctrineroutecollectio/</feedburner:origLink></item>
		<item>
		<title>Symfony: Symfony Day 2010 в Кёльне</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/ppFOAvxY9lg/</link>
		<comments>http://www.charnad.com/blog/symfony-day-2010-in-cologne/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 09:40:33 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1210</guid>
		<description><![CDATA[Как, наверное, некоторые из вас знают, 8 октября прошла конференция Symfony Day 2010 в Кёльне, на которой мне посчастливилось присутствовать. Я случайно наткнулся на сайт, http://www.symfonyday.com/, и сразу же решил, что хочу туда. Вход стоил 120 евро, но я успел как early bird за 80. Путь мой начинался с самой восточной границы Германии, и лежал [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />
<p>Как, наверное, некоторые из вас знают, 8 октября прошла конференция Symfony Day 2010 в Кёльне, на которой мне посчастливилось присутствовать. Я случайно наткнулся на сайт, <a href="http://www.symfonyday.com/">http://www.symfonyday.com/</a>, и сразу же решил, что хочу туда. Вход стоил 120 евро, но я успел как early bird за 80. Путь мой начинался с самой восточной границы Германии<span id="more-1210"></span>, и лежал почти до западной, более 550 километров, причем ночью. Не хотелось тратиться на гостиницу, а тут еще подвернулся вариант с CNL (ночным) поездом, я думал, что это вроде плацкартного. Как выяснилось, место у меня сидячее, в купе едут по 6 человек, спать было почти невозможно. Так что приехал я в Кёльн за 3 часа до конференции весьма измотанный.
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7696.jpg" title="" class="shutterset_singlepic90" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/90__160x120_dsc_7696.jpg" alt="dsc_7696" title="dsc_7696" />
</a>
</p>
<p>На входе в медиа-центре Komed, где происходило действие, красовались флаги Symfony Day. Нам выдали беджики, и мы пошли в зал. Было еще рано, поэтому народу почти не было, зато на экране запустили Twitterwall - прямую трансляцию из Твиттера по хештегу #sfdaycgn, сделанную с помощью node.js. Я не преминул возможностью передать привет всем присутствующим от друзей из Russian Symfony User Group <img src='http://www.charnad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> .
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7700.jpg" title="" class="shutterset_singlepic92" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/92__160x120_dsc_7700.jpg" alt="dsc_7700" title="dsc_7700" />
</a>
</p>
<p>Первым выступал Jonathan Wage, который рассказал о работе Doctrine 2 с Mongo DB. Он вкратце обьяснил что же за зверь такой этот Mongo DB, и привел примеры, как с помощью Doctrine делать самые обычные действия - прочитать/вставить/удалить. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7702.jpg" title="" class="shutterset_singlepic94" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/94__160x120_dsc_7702.jpg" alt="dsc_7702" title="dsc_7702" />
</a>
 Доклад был интересным, однако слушал я с трудом. Сказалась ночь в поезде и меня жутко клонило в сон. Не припомню когда я еще проявлял столько воли, чтобы не засыпать и не зевать. Сразу после я побежал заливаться кофе, а вы пока можете посмотреть слайды.
<div style="width:425px" id="__ss_5393200"><object id="__sse5393200" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=symfonyday2010mongodbodm-101008082122-phpapp01&#038;stripped_title=symfony-day-2010-doctrine-mongodb-odm&#038;userName=jwage" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5393200" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=symfonyday2010mongodbodm-101008082122-phpapp01&#038;stripped_title=symfony-day-2010-doctrine-mongodb-odm&#038;userName=jwage" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
</p>
<p> Вторым выступал core developer PHP Pierre Joye. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7704.jpg" title="" class="shutterset_singlepic96" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/96__160x120_dsc_7704.jpg" alt="dsc_7704" title="dsc_7704" />
</a>
Этот доклад был наполнен юмором. Если доклад Джонатана был вроде утренних новостей, то доклад Пьера как первая развлекательная передача дня. Рассказ был о том, как развивается PHP, какие есть недостатки, и что с этим можно делать. В зале нашелся человек, который до сих пор пользуется PHP4. Угадайте, какую CMF он использует? Правильно, Drupal. А вот вам цитатка:"A lot of idiots use PHP. For example.. (slide) Microsoft". Главным слайдом презентации можно считать "PHP is ugly". Да, разработчик PHP признает, что язык уродлив. Но мы же не художники в конце концов. Нам не о красоте надо думать, а о том, как создавать проекты, которые будут успешно работать. К тому же, если использовать Symfony, то недостатки заметны меньше. Да и помимо Symfony написано достаточно хороших фреймворков, и вряд ли есть большой спрос на новые. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7705.jpg" title="" class="shutterset_singlepic97" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/97__160x120_dsc_7705.jpg" alt="dsc_7705" title="dsc_7705" />
</a>
 "Кто вообще писал новый фреймворк за последние два года",- вопрошал Пьер. Руку поднял один человек в зале - Фабьен Потенсьер <img src='http://www.charnad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  Все засмеялись и заапплодировали. Важной мыслью было то, что PHP уже достиг того когда он почти никогда не является "бутылочным горлышком". "Если вам не хватает производительности PHP - то вы Facebook".
<div style="width:425px" id="__ss_5392819"><object id="__sse5392819" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=phpsymfonyandsoftwarelifecycle-101008073640-phpapp01&#038;rel=0&#038;stripped_title=php-symfony-and-software-lifecycle&#038;userName=pierrej" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5392819" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=phpsymfonyandsoftwarelifecycle-101008073640-phpapp01&#038;rel=0&#038;stripped_title=php-symfony-and-software-lifecycle&#038;userName=pierrej" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
</p>
<p>Пока был перерыв перед следующим докладом - я сделал фотографию зала. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7706.jpg" title="" class="shutterset_singlepic98" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/98__160x120_dsc_7706.jpg" alt="dsc_7706" title="dsc_7706" />
</a>
 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7708.jpg" title="" class="shutterset_singlepic99" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/99__160x120_dsc_7708.jpg" alt="dsc_7708" title="dsc_7708" />
</a>
 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7710.jpg" title="" class="shutterset_singlepic100" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/100__160x120_dsc_7710.jpg" alt="dsc_7710" title="dsc_7710" />
</a>
 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7711.jpg" title="" class="shutterset_singlepic101" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/101__160x120_dsc_7711.jpg" alt="dsc_7711" title="dsc_7711" />
</a>
 По количеству стульев можно прикинуть, что было человек 150. А выступал третьим Christian Schaefer (Кристиан Шефер), симфони-блоггер. Может я ошибаюсь, но мне показалось, что у него не очень большой опыт подобного рода выступлений - в основном он повторял то, что было написано на слайдах. Тем не менее, слушать было интересно. А речь шла о Unit-тестировании плагинов с помощью PHPUnit. О том, как все правильно настроить, и как тесты запускать.
<div style="width:425px" id="__ss_5401851"><object id="__sse5401851" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=unittestingsymfonypluginswithphpunit-101009132914-phpapp01&#038;stripped_title=unit-testing-symfony-plugins-with-php-unit-5401851&#038;userName=caefer" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5401851" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=unittestingsymfonypluginswithphpunit-101009132914-phpapp01&#038;stripped_title=unit-testing-symfony-plugins-with-php-unit-5401851&#038;userName=caefer" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
</p>
<p>После 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7713.jpg" title="" class="shutterset_singlepic102" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/102__160x120_dsc_7713.jpg" alt="dsc_7713" title="dsc_7713" />
</a>
 третьего доклада был перерыв, и в холле можно было было вкусно покушать. А я же в первую очередь побежал делать эту фотографию. Так же в перерыве познакомились и немного поболтали с Антоном Бобенко, сам он из Украины, работает в Норвегии. Не знаю, был ли кто-нибудь еще из русскоязычных.
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7715.jpg" title="" class="shutterset_singlepic103" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/103__160x120_dsc_7715.jpg" alt="dsc_7715" title="dsc_7715" />
</a>
</p>
<p>Подошло время четвертого доклада, выступал Крис Уолсмит. Довольно вальяжно и, может быть даже, слегка небрежно Крис рассказал о различных техниках, которые можно применить в проекте. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7717.jpg" title="" class="shutterset_singlepic104" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/104__160x120_dsc_7717.jpg" alt="dsc_7717" title="dsc_7717" />
</a>
Например, если закончилась сессия, пока редактировалась форма, или как динамически добавлять несколько встроенных форм. Пожалуй, в этом докладе были наиболее полезные советы, которые можно применить на практике. Единственное что под конец каждого примера я уже терялся в коде и не мог полностью понять все детали. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7719.jpg" title="" class="shutterset_singlepic105" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/105__160x120_dsc_7719.jpg" alt="dsc_7719" title="dsc_7719" />
</a>
 Тем не менее общую идею уловил и понял. </p>
<div style="width:425px" id="__ss_5396592"><object id="__sse5396592" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=advanced-symfony-techniques-101008164721-phpapp02&#038;stripped_title=advanced-symfony-techniques&#038;userName=kriswallsmith" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5396592" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=advanced-symfony-techniques-101008164721-phpapp02&#038;stripped_title=advanced-symfony-techniques&#038;userName=kriswallsmith" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
</p>
<p>Следующим выступал Гейлорд Олке (Gaylord Aulke). 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7721.jpg" title="" class="shutterset_singlepic107" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/107__160x120_dsc_7721.jpg" alt="dsc_7721" title="dsc_7721" />
</a>
 Этот доклад был, я думаю, не столько для программистов, сколько для работников отдела продаж. Гейлорд рассказал о том, как представить клиенту выбор, покупать готовый сайт, который можно просто запустить, или заказывать разработку, которая займет время, но зато проект будет соответствовать пожеланиям клиента. Есть еще третий вариант - построить проект из модулей. </p>
<p>Последним выступал Фабьен Потенсьер. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7723.jpg" title="" class="shutterset_singlepic109" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/109__160x120_dsc_7723.jpg" alt="dsc_7723" title="dsc_7723" />
</a>
 Речь шла о Symfony2, которая должна быть готова к марту 2011. Во-первых, для темплейтов можно будет использовать шаблонизатор Twig. И хотя поддержка чистого PHP останется, Twig гораздо более прост для восприятия и использования непрограммистом. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7724.jpg" title="" class="shutterset_singlepic110" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/110__160x120_dsc_7724.jpg" alt="dsc_7724" title="dsc_7724" />
</a>
 Пользователь, как объект, теперь не привязан к сессии, пользовательские данные можно будет хранить в конфиг-файле (например, если нужен только один админ), можно будет одновременно аутентифицировать пользователей через БД, LDAP и конфиг файлы. Формы можно будет показывать с помощью темплейтов, того же твига. В общем масса изменений, все будет супер-круто. Ну и приложу слайд, который будет во всех блогах и отчетах про конференцию <img src='http://www.charnad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />
<div style="width:425px" id="__ss_5399986"><object id="__sse5399986" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=symfony2-101009070646-phpapp02&#038;stripped_title=the-state-of-symfony2-symfonyday-2010&#038;userName=fabpot" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed name="__sse5399986" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=symfony2-101009070646-phpapp02&#038;stripped_title=the-state-of-symfony2-symfonyday-2010&#038;userName=fabpot" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object></div>
</p>
<p>Фабьен дольше всех отвечал на вопросы, что в общем неудивительно. Когда все закончилось в холле было бесплатное пиво, небольшой конкурс с призами (я ничего не выиграл), можно было набрать наклеек. Ощущения, конечно, самые позитивные. 
<a href="http://www.charnad.com/blog/wp-content/gallery/symfony-day-2010/dsc_7728.jpg" title="" class="shutterset_singlepic111" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/111__160x120_dsc_7728.jpg" alt="dsc_7728" title="dsc_7728" />
</a>
  Больше всего понравились выступления Пьера Жойе и Фабьена Потенсьера, а самым полезным я считаю доклад Криса Уолсмита. Приложу еще фотографию Кёльнского собора, раз уж я там был, грех был бы не посмотреть.</p>
<p>Через пару часов я сел на поезд и отправился домой, опять более чем 550 километров сидя, ночью. Поспать мне опять не удалось и после двух бессонных ночей чувствовал я себя.. да почти не чувствовал. Но эти мелочи не могли повлиять на удовольствие, которое я получил на конференции: побыл среди умных людей, послушал выступления и вообще классно провел время.</p>
<p>Для эксперимента еще выложил фотографии на <a href="http://www.flickr.com/photos/54686499@N02/5064087515/in/set-72157625000809289/">flickr</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-day-2010-in-cologne/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-day-2010-in-cologne/</feedburner:origLink></item>
		<item>
		<title>Symfony: иерархический URL</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/eqrqTCnrLeE/</link>
		<comments>http://www.charnad.com/blog/symfony-hierarcial-url/#comments</comments>
		<pubDate>Wed, 15 Sep 2010 12:04:17 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[routing]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1202</guid>
		<description><![CDATA[Наверняка многие имеют некие иерархические данные в своем проекте, будь то категории с подкатегориями, страницы с подстраницами и все такое прочее. Как подобные объекты выводятся пользователю? Обычно с помощью роута типа /category/1, или /page/28, где число - это id объекта, или даже /page/delivery, где используется slug. Но все это не отражает иерархичность наших данных. Иногда [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />Наверняка многие имеют некие иерархические данные в своем проекте, будь то категории с подкатегориями, страницы с подстраницами и все такое прочее. Как подобные объекты выводятся пользователю? Обычно с помощью роута типа /category/1, или /page/28, где число - это id объекта, или даже /page/delivery, где используется slug. Но все это не отражает иерархичность наших данных. Иногда же хочется /page/delivery/small-items и /page/delivery/large-items. Никто не мешает сделать дополнительный роут с двумя слагами, но ведь их может быть не два, а три, и не три, а пять.<br />
<span id="more-1202"></span></p>
<p>Сразу оговорюсь, речь опять пойдет о плагине. Всю функциональность проекта я стараюсь реализовывать в плагинах, если есть хоть малейший намек на то, что это может потребоваться где-то еще. В конкретном случае модуль для статических страниц (в схеме: заголовок, текст, слаг, метаполя). И вот важный момент, для плагинов можно создать файл PLUGINNAMEConfiguration.class.php. Нам это пригодится тем, что мы будем создавать роуты на лету, начиная как раз с этого файла.</p>
<p>Обычно я убираю названия плагинов/модулей из листингов, но в данном случае ради наглядности и простоты понимания я их оставлю. Плагин называется wePages, модуль wePages_frontend. И вот значит что мы будем делать в конфигурации:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> initialize<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wePages_frontend'</span><span style="color: #339933;">,</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'sf_enabled_modules'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">dispatcher</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'routing.load_configuration'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wePagesRouting'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'listenToRoutingLoadConfigurationEvent'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Если наш модуль числится в списке подключенных, то подключаем listener по имени listenToRoutingLoadConfigurationEvent из файла wePagesRouting к событию routing.load_configuration. Проще говоря, когда загрузится конфигурация роутов будет вызвана наша функция.
</p>
<p>Создадим файл /lib/routing/wePagesRouting.class.php, куда поместим нашу функцию.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> wePagesRouting <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Listens to the routing.load_configuration event.
   *
   * @param sfEvent An sfEvent instance
   * @static
   */</span>
  static <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> listenToRoutingLoadConfigurationEvent<span style="color: #009900;">&#40;</span>sfEvent <span style="color: #000088;">$event</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$r</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$event</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getSubject</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Узнаем максимальную глубину дерева</span>
    <span style="color: #000088;">$maxlvl</span> <span style="color: #339933;">=</span> Doctrine_Query<span style="color: #339933;">::</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
              <span style="color: #004000;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MAX(level) as maxlvl'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
              <span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wePages'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span> 
              <span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
              <span style="color: #004000;">getFirst</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span>
              <span style="color: #004000;">getMaxlvl</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// В конфигурации мы можем указать префикс для роута, </span>
    <span style="color: #666666; font-style: italic;">// например '/page', начинаться же он должен со слеша, </span>
    <span style="color: #666666; font-style: italic;">// что мы и проверяем</span>
    <span style="color: #666666; font-style: italic;">// prefix must have '/' </span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span>sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_we_pages_plugin_route_prefix'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$route_pattern</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'/'</span><span style="color: #339933;">.</span><span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_we_pages_plugin_route_prefix'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">''</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$route_pattern</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">''</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Здесь мы создаем строчку, на соответствие которой в роутинге </span>
    <span style="color: #666666; font-style: italic;">// будет проверятся URL, тут-то и кроется вся магия. </span>
    <span style="color: #666666; font-style: italic;">// Мы создаем роут с количеством слагов равным максимальной </span>
    <span style="color: #666666; font-style: italic;">// глубине дерева, чтобы охватить все страницы, а в качестве </span>
    <span style="color: #666666; font-style: italic;">// значения по умолчанию ставим false, чтобы роут срабатывал </span>
    <span style="color: #666666; font-style: italic;">// и на меньшем количестве слагов</span>
    <span style="color: #000088;">$defaults</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;=</span> <span style="color: #000088;">$maxlvl</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$route_pattern</span> <span style="color: #339933;">.=</span> <span style="color: #0000ff;">'/:slug'</span><span style="color: #339933;">.</span><span style="color: #000088;">$i</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$defaults</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'slug'</span><span style="color: #339933;">.</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// осталось теперь только подключить роут к уже загруженным, </span>
    <span style="color: #666666; font-style: italic;">// важно чтобы он был первым</span>
    <span style="color: #666666; font-style: italic;">// preprend our routes</span>
    <span style="color: #000088;">$route</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> wePagesRoute<span style="color: #009900;">&#40;</span>
        <span style="color: #000088;">$route_pattern</span><span style="color: #339933;">,</span> 
        <span style="color: #990000;">array_merge</span><span style="color: #009900;">&#40;</span> 
            <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span> <span style="color: #0000ff;">'module'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'wePages_frontend'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'action'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'show'</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> 
            <span style="color: #000088;">$defaults</span> 
        <span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$r</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">prependRoute</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wePages_frontend'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$route</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Надеюсь, что в комментариях я обьяснил достаточно подробно что мы делаем. Создали роут, который охватывает все страницы сразу, с большим и маленьким количеством слагов.</p>
<p>Обратите внимание, что мы создали объет не sfRoute, а wePagesRoute. Этот класс лежит в соседнем файле wePagesRoute.class.php. Нам ведь надо проверять довольно специфические условия, поэтому стандартный класс не подходит.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> wePagesRoute <span style="color: #000000; font-weight: bold;">extends</span> sfRoute <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// функция проверяет подходит ли данный роут под указанный URL</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> matchesUrl<span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #000088;">$context</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// если шаблон роута не совпадает - дальше даже не смотрим</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$parameters</span> <span style="color: #339933;">=</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">matchesUrl</span><span style="color: #009900;">&#40;</span> <span style="color: #990000;">rtrim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'/'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">,</span> <span style="color: #000088;">$context</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">// преобразуем наши сгенерированные слаги в массив, </span>
    <span style="color: #666666; font-style: italic;">// где ключи - это глубина элемента в дереве,</span>
    <span style="color: #666666; font-style: italic;">// а значения - сами слаги.</span>
    <span style="color: #666666; font-style: italic;">// почему так? у нас же рекурсивный роут и начинается </span>
    <span style="color: #666666; font-style: italic;">// с верхнего уровня, который имеет level = 0</span>
    <span style="color: #666666; font-style: italic;">// соответственно следующие слаги имеют level = 1,2,3..</span>
    <span style="color: #666666; font-style: italic;">// make slug1, slug2.. into array [0] =&gt; 'slug1', [1] =&gt; 'slug2'</span>
    <span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$pages</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">isset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$parameters</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'slug'</span><span style="color: #339933;">.</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #990000;">strlen</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$parameters</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'slug'</span><span style="color: #339933;">.</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$pages</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$parameters</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'slug'</span><span style="color: #339933;">.</span><span style="color: #000088;">$i</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$i</span><span style="color: #339933;">++;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// если выяснилось, что слагов не указано - бросаем это дело</span>
    <span style="color: #666666; font-style: italic;">// If we dont have any slugs - we dont want this anymore</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">empty</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #666666; font-style: italic;">// Второй важный момент</span>
    <span style="color: #666666; font-style: italic;">// Мы берем слаги и уровни, и ищем страницы подходящие под условия. </span>
    <span style="color: #666666; font-style: italic;">// Данный способ не работает, если slug не уникальны.</span>
    <span style="color: #666666; font-style: italic;">// Groupby объединяет элементы с одинаковым уровнем</span>
    <span style="color: #666666; font-style: italic;">// Get pages with these slugs and levels</span>
    <span style="color: #000088;">$data</span> <span style="color: #339933;">=</span> Doctrine_Query<span style="color: #339933;">::</span><span style="color: #004000;">create</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">from</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'wePages'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhereIn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'slug'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array_values</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhereIn</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'level'</span><span style="color: #339933;">,</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">orderBy</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'level ASC, lft ASC'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #666666; font-style: italic;">// this group by removes entries with same level</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">groupBy</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'level'</span><span style="color: #009900;">&#41;</span>
        <span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// теперь внимательно смотрим, если нашли страниц меньше, </span>
    <span style="color: #666666; font-style: italic;">// чем было указано слагов то URL не совпадает с иерархией в БД, </span>
    <span style="color: #666666; font-style: italic;">// а значит, извините, но вы не по адресу.</span>
    <span style="color: #666666; font-style: italic;">// искали 3 слага - надо найти 3 страницы, и чтобы их level </span>
    <span style="color: #666666; font-style: italic;">// были равны 0,1,2 и не повторялись</span>
    <span style="color: #666666; font-style: italic;">// проблемы начнутся, если слаги могут совпадать, </span>
    <span style="color: #666666; font-style: italic;">// но другого быстрого и простого способа проверить я не придумал</span>
    <span style="color: #666666; font-style: italic;">// If some url parts dont fit - dont want this anymore</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$data</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&lt;</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$pages</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// если мы не указали в конфигурации префикс </span>
    <span style="color: #666666; font-style: italic;">// и страницы вызываются, как www.site.com/page1</span>
    <span style="color: #666666; font-style: italic;">// то этот роут будет выполнятся довольно часто, </span>
    <span style="color: #666666; font-style: italic;">// поэтому раз уж мы выполнили поиск страниц</span>
    <span style="color: #666666; font-style: italic;">// было бы глупо не передать уже найденный id в метод show,</span>
    <span style="color: #666666; font-style: italic;">// или что там у вас для показа</span>
    <span style="color: #000088;">$parameters</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'page_id'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$data</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLast</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getId</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$parameters</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

</p>
<p>У меня этот метод прекрасно заработал, хотя и не является идеальным решением. Если я хочу создать страницы /team/men, /team/women, то мне придется создавать и страницу /team, и она будет открываться, хотя я, например, хотел бы чтобы она редиректила на /team/men. То есть надо было бы создавать тип страниц "редирект". Что порядком костыльно. Так же, вероятно, будут проблемы с link_to и url_for. Стоит написать свой хелпер для генерации урлов.</p>
<p>Что еще можно сделать? Можно при создании страницы указывать URL напрямую, и хранить его в БД. И точно так же в роуте проверять не соответствие слагов и уровней, а просто искать по полю url. Позволяет обойти проблему с /team/men, хотя и не очень красиво, страница /team, будет выдавать 404. Хотя как я понимаю, проблему с link_to оно все равно не решит.</p>
<p>Все описанные способы являются экспериментальными, где-то может вылезти проблема о которой я не догадывался. Так что воспринимайте это как концепцию, а если вы найдете более удачный способ и напишете мне - я буду благодарен. </p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-hierarcial-url/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-hierarcial-url/</feedburner:origLink></item>
		<item>
		<title>Symfony: свой фильтр в admin generator</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/aOeu2i9NKio/</link>
		<comments>http://www.charnad.com/blog/symfony-custom-filter-in-admin-generator/#comments</comments>
		<pubDate>Wed, 08 Sep 2010 18:38:02 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[form filter]]></category>
		<category><![CDATA[symfony]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1193</guid>
		<description><![CDATA[Кратко о том, как сделать фильтр для админ генератора. В моем проекте используется Doctrine с поведением NestedSet, и фильтр мне нужен был по родительскому полю. Точнее, показать потомков выбранного элемента. Для этого я пошел в папку /lib/filters и открыл файл фильтров для нужной модели. Там будем править метод configure. В моем случае дело происходит в [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />Кратко о том, как сделать фильтр для админ генератора. В моем проекте используется Doctrine с поведением NestedSet, и фильтр мне нужен был по родительскому полю. Точнее, показать потомков выбранного элемента. Для этого я пошел в папку /lib/filters и открыл файл фильтров для нужной модели. Там будем править метод configure. В моем случае дело происходит в плагине, поэтому метод, который я буду править называется setupInheritance.<br />
<span id="more-1193"></span></p>
<p>
<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span>  setupInheritance<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">setupInheritance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfWidgetFormDoctrineChoiceNestedSet<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'model'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'MODEL_NAME'</span><span style="color: #339933;">,</span>
        <span style="color: #0000ff;">'add_empty'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">true</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> sfValidatorDoctrineChoice<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'model'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">'MODEL_NAME'</span><span style="color: #339933;">,</span> 
        <span style="color: #0000ff;">'required'</span> <span style="color: #339933;">=&gt;</span> <span style="color: #009900; font-weight: bold;">false</span>
    <span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Добавили виджет и валидатор. sfWidgetFormDoctrineChoiceNestedSet это простой DoctrineChoice, в котором есть отступы и сортировка в соответствии с иерархией в NestedSet. Теперь наш виджет виден в форме, правда ни на что пока не влияет.</p>
<p>Чтобы на что-то влиять, нам надо добавить его в список полей фильтра в том же файле.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getFields<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$fields</span> <span style="color: #339933;">=</span> parent<span style="color: #339933;">::</span><span style="color: #004000;">getFields</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$fields</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'parent'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'NestedNode'</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$fields</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Здесь надо обратить внимание не только на значение, но и на имя ключа в массиве. В качестве значения можно указывать "Number", "Text", "Date" и некоторые другие. Я не пробовал, но полагаю, что если указать одно из них, то сработает стандартный обработчик поля фильтра, как например addNumberQuery. В нашем случае формат нестандартный и обработчик будем делать сами.
</p>
<p>Кстати говоря, если в данный момент посмотреть на наш проект - нам выбросят исключение, где будет сказано как надо назвать метод, который будет обрабатывать наше поле. В моем случае это addParentColumnQuery. Формат названия функции, скорее всего такой: add_COLUMN_NAME_ColumnQuery.<br />
А собственно вот и она сама:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> addParentColumnQuery<span style="color: #009900;">&#40;</span><span style="color: #000088;">$q</span><span style="color: #339933;">,</span> <span style="color: #000088;">$element</span><span style="color: #339933;">,</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$parent</span> <span style="color: #339933;">=</span> Doctrine<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'MODEL_NAME'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">findOneById</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$q</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhere</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lft &gt; ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getLft</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">andWhere</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'rgt &lt; ?'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$parent</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getRgt</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Получаем Doctrine_Query в качестве параметра $q, добавляем свои условия и возвращаем. Все легко и просто. <br/><br />
Наздоровье <img src='http://www.charnad.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /><br />
Референс: <a href="http://robert-says.com/2010/03/symfony-how-to-add-a-custom-filter-for-the-admin-listing/">http://robert-says.com/2010/03/symfony-how-to-add-a-custom-filter-for-the-admin-listing/</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-custom-filter-in-admin-generator/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-custom-filter-in-admin-generator/</feedburner:origLink></item>
		<item>
		<title>Symfony: Optgroup в DoctrineChoice</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/RnGqhOpH6yY/</link>
		<comments>http://www.charnad.com/blog/symfony-optgroup-v-doctrinechoice/#comments</comments>
		<pubDate>Wed, 18 Aug 2010 11:11:56 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[form]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[widget]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1186</guid>
		<description><![CDATA[Потребовалось мне сделать optgroup в виджете choice, и не просто так, а с условием. Если у объекта есть дочерние элементы - то он становится optgroup, а иначе его можно выбрать. За основу я взял sfWidgetFormDoctrineChoiceNestedSet, который можно взять из плагина sfDoctrineNestedSetPlugin. Я скопировал код, добавил в запрос условие: $query->addWhere('level = ?', 0); Это потому, что [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />Потребовалось мне сделать optgroup в виджете choice, и не просто так, а с условием. Если у объекта есть дочерние элементы - то он становится optgroup, а иначе его можно выбрать. За основу я взял sfWidgetFormDoctrineChoiceNestedSet, который можно взять из плагина <a href="http://www.symfony-project.org/plugins/sfDoctrineNestedSetPlugin">sfDoctrineNestedSetPlugin</a>. Я скопировал код, добавил в запрос условие:</p>
<pre class="php">$query->addWhere('level = ?', 0);</pre>
<p>Это потому, что все, что ниже уровнем мы будем получать через getChildren. Иначе нам пришлось бы двигать итератор Doctrine_Collection, что более сложно, заумно, и вовсе у меня не получилось (next($objects) почему-то не дает эффекта).<br />
Сделать optgroup в choice совсем несложно, надо лишь сделать элемент массивом. Ну а что получилось собственно внутри поста.<br />
<span id="more-1186"></span><br />
Я еще раз повторюсь, что это код sfWidgetFormDoctrineChoiceNestedSet, за малым изменением.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">class</span> weDoctineOptgroupSelectWidget <span style="color: #000000; font-weight: bold;">extends</span> sfWidgetFormDoctrineChoice <span style="color: #009900;">&#123;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> getChoices<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$choices</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">false</span> <span style="color: #339933;">!==</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'add_empty'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$choices</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">''</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">true</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'add_empty'</span><span style="color: #009900;">&#41;</span> ? <span style="color: #0000ff;">''</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'add_empty'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table_method'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$query</span> <span style="color: #339933;">=</span> <span style="color: #009900; font-weight: bold;">null</span> <span style="color: #339933;">===</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query'</span><span style="color: #009900;">&#41;</span> ? Doctrine_Core<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'model'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">createQuery</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">:</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'query'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #666666; font-style: italic;">// force manual sorting according to root_id then by lft</span>
      <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOrderBy</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'root_id asc'</span><span style="color: #009900;">&#41;</span>
          <span style="color: #339933;">-&gt;</span><span style="color: #004000;">addOrderBy</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'lft asc'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #666666; font-style: italic;">// Viktoras: we need to fetch only top level, as we'll get the children with getChildren()</span>
      <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">addWhere</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'level = ?'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$objects</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$query</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$tableMethod</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'table_method'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #000088;">$results</span> <span style="color: #339933;">=</span> Doctrine_Core<span style="color: #339933;">::</span><span style="color: #004000;">getTable</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'model'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$tableMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span> instanceof Doctrine_Query<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$objects</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$results</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">execute</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span> instanceof Doctrine_Collection<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$objects</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$results</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$results</span> instanceof Doctrine_Record<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$objects</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Doctrine_Collection<span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'model'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$objects</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$results</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$objects</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #000088;">$method</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'method'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$keyMethod</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'key_method'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$objects</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$object</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      <span style="color: #666666; font-style: italic;">// indent item by 4 spaces per level</span>
      <span style="color: #666666; font-style: italic;">// Viktoras: here we check for children and make entry an array if they exists</span>
      <span style="color: #000088;">$node</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$object</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNode</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">hasChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$node</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getChildren</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$child</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
          <span style="color: #000088;">$choices</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$object</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$method</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$keyMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">str_repeat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&amp;nbsp;'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$child</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'level'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$child</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$method</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
      <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$choices</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$object</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$keyMethod</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #990000;">str_repeat</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'&amp;nbsp;'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$object</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'level'</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">*</span> <span style="color: #cc66cc;">4</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">.</span> <span style="color: #000088;">$object</span><span style="color: #339933;">-&gt;</span><span style="color: #000088;">$method</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #000088;">$choices</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>И выглядит это вот так:<br />
<img src="http://img405.imageshack.us/img405/8427/12ece8ab6752487cafefb3c.png"></p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-optgroup-v-doctrinechoice/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-optgroup-v-doctrinechoice/</feedburner:origLink></item>
		<item>
		<title>Symfony Tips: #1</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/GsFBW_o1PFY/</link>
		<comments>http://www.charnad.com/blog/symfony-tips-1/#comments</comments>
		<pubDate>Thu, 01 Jul 2010 15:50:21 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[admin generator]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[symfony tips]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1178</guid>
		<description><![CDATA[Бывает, что находишь какое-то решение в Гугле, а потом когда я сталкиваешься с похожей ситуацией - второй раз уже не можешь найти. Поэтому я буду записывать моменты, которые мне были полезны и могут понадобиться еще, будет что-то вроде рубрики Symfony tips. Как вообще убрать фильтры в admin generator? config: filter: class: false Как повесить иконку [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />Бывает, что находишь какое-то решение в Гугле, а потом когда я сталкиваешься с похожей ситуацией - второй раз уже не можешь найти. Поэтому я буду записывать моменты, которые мне были полезны и могут понадобиться еще, будет что-то вроде рубрики Symfony tips.</p>
<p><strong>Как вообще убрать фильтры в admin generator?</strong></p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">config:
  filter:
    class: false</pre></div></div>

</p>
<p><strong>Как повесить иконку своему кастомному object_action?</strong></p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #cc00cc;">#sf_admin_container</span> ul li<span style="color: #6666ff;">.sf_admin_action_</span>#<span style="color: #cc00cc;">#ACTION_NAME</span>## a
<span style="color: #00AA00;">&#123;</span>
  <span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">/images/icons/icon.png</span><span style="color: #00AA00;">&#41;</span> <span style="color: #993333;">no-repeat</span> <span style="color: #cc66cc;">0</span> <span style="color: #cc66cc;">0</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

</p>
<p><strong>Как недопустить ввода пустой строки в админке?</strong></p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">validatorSchema</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'name'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setOption</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'trim'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

</p>
<p><strong>Fatal error: Call to undefined function include_component()</strong><br />
Вы, скорее всего, указали в settings.yml standart_helpers, и забыли добавить в список Partial.</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">all: 
  .settings: 
    standard_helpers:       [I18N, Partial]</pre></div></div>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-tips-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-tips-1/</feedburner:origLink></item>
		<item>
		<title>Поездка в Чехию. Часть 1.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/YCaPgvb-Zkk/</link>
		<comments>http://www.charnad.com/blog/poezdka-v-czechiu-part-1/#comments</comments>
		<pubDate>Wed, 23 Jun 2010 22:11:02 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[Прочее]]></category>
		<category><![CDATA[travel]]></category>
		<category><![CDATA[Чехия]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1116</guid>
		<description><![CDATA[18 июня исполнился год с момента нашей свадьбы, и это событие мы решили отметить поездкой в Чехию. Ехали, конечно же, в Прагу. В планах было посмотреть старый город, Влтаву (река, на которой стоит Прага), мосты, покушать чешской еды и попробовать чешское пиво в самой Чехии. И сейчас я вам расскажу как это было. За день [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/czechia.png" alt="Czechia" />18 июня исполнился год с момента нашей свадьбы, и это событие мы решили отметить поездкой в Чехию. Ехали, конечно же, в Прагу. В планах было посмотреть старый город, Влтаву (река, на которой стоит Прага), мосты, покушать чешской еды и попробовать чешское пиво в самой Чехии. И сейчас я вам расскажу как это было.</p>
<p>За день до поездки мы искали отель, так как собирались пробыть в Праге два дня, а так же изучали карту города и смотрели сайты ресторанов, выбирая поинтереснее и подешевле. Сразу дам ссылочку на <a href="http://www.pragueexperience.com/">сайт</a>, который нам сильно помог. Как раз там мы и заказали номер. Изначально хотели взять что подешевле, но все оказалось уже занятым, поэтому взяли номер на двоих в 4х-звездочном небольшом отеле <a href="http://www.pragueexperience.com/places.asp?PlaceID=711">Antik</a> за 60 евро, включая завтрак. Чуть забегая вперед скажу, что это составило чуть меньше половины всех наших затрат на это путешествие.<span id="more-1116"></span></p>
<p>Отправились мы из Zittau в 8:45 на поезде до города <a href="http://maps.google.com/maps?hl=en&#038;jsv=250a&#038;sll=50.766594,15.065947&#038;sspn=0.02926,0.077162&#038;ie=UTF8&#038;geocode=FaykBgMdB73lAA&#038;split=0">Liberec</a>. Билеты купили заранее, стоили они всего €2,60 на человека. Дорога заняла всего 35 минут, и в 9:20 мы уже были на месте. </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic69" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/69__x_dsc_5819.jpg" alt="dsc_5819" title="dsc_5819" />
</a>

<p>Либерецкий вокзал на ремонте и выходить пришлось какими-то грязными корридорами. Как вышли - побежали на автобусный вокзал, уж очень хотели успеть на автобус на 10 часов. Для чешских автобусов есть очень удобный сайт <a href="http://www.zluty.cz/online/Booking">Student Agency</a>, где можно заказать билет заранее и оплатить, а потом при входе просто сказать номер своей брони. При бронировании можно увидеть сколько мест осталось свободно и выбрать какие именно места хотите. </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic68" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/68__x_dsc_5815.jpg" alt="dsc_5815" title="dsc_5815" />
</a>

<p>И вот за день до отъезда я хотел забронировать нам места в автобусе на 10 часов, но к сожалению, моя банковская карта не подходит для оплаты через интернет, а мест в автобусе оставалось всего 7. К нашему счастью мы успели купить билеты. До отправления оставалось около 30 минут, так что мы немного погуляли вокруг вокзала, или как его там называют Nádraží.</p>
<p>Ровно в 10 часов подошел наш автобус, такие называют coach. Наши места были 29,30 — как раз напротив входа. Здесь мы были порядком удивлены. За билеты мы заплатили 160 чешских крон, что равно примерно 6 евро. При этом в автобусе было несколько экранов, где можно было смотреть сериал «Друзья» на английском с чешскими субтитрами, для этого бесплатно выдаются наушники. Кроме того стюардесса бесплатно приносит горячие напитки (чай, кофе, горячий шоколад), а для желающих есть туалет. Хотелось встряхнуть головой и протереть глаза, неужели и правда это все за 3 евро с человека. И ведь еще везут куда надо... поразительно. Через 1 час и 5 минут мы приехали в Прагу. Всего получается мы потратили на дорогу 2 часа и 11 евро.</p>

<a href="javascript:return false;" title="" class="shutterset_singlepic70" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/70__x_dsc_5822.jpg" alt="dsc_5822" title="dsc_5822" />
</a>

<p>Прибыли мы на автобусный вокзал, где находится станция метро Černý Most. Я думаю несложно догадаться, что по-русски это будет «Черный мост». Вход в метро здесь немного похож на финский, никаких тебе турникетов, только стойки для компостирования билетов. Вот чего я вам не советую, так это приезжать в Прагу в воскресенье - кассы не работают, а автоматы принимают только монеты. Так что с вашими евро, или банкотами из банкомата, придется искать место, где продают билеты.</p>

<a href="javascript:return false;" title="" class="shutterset_singlepic72" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/72__x_dsc_5824.jpg" alt="dsc_5824" title="dsc_5824" />
</a>

<p>Благо они бывюат в газетных киосках, да и вообще в магазинах рядом с метро. Билеты тут действуют определенное количество времени. Есть билет на 20 минут за 18 крон, но на нем далеко не уедешь. Чтобы доехать до центра от Černý Most — берите лучше билет за 26 крон, он будет действовать 75 минут с момента активации. Можно так же взять билеты на 1-3-5 дней (100-330-500 крон соответственно).</p>

<a href="javascript:return false;" title="" class="shutterset_singlepic75" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/75__x_dsc_6652.jpg" alt="dsc_6652" title="dsc_6652" />
</a>

<p>При входе в любой транспорт неактивированный билет надо активировать, засунув его в специальный аппарат. Как раз такие и стоят на входе в метро. Будьте внимательны, компостируйте с правильной стороны! Когда мы уже ехали обратно, моя жена неправильно прокомпостировала билет. Заметили не сразу, но решили, что ничего страшного. Так вот у нас обошлось, но вообще штраф 1000 крон, независимо от того что вы иностранец и не понимаете их язык и как у них все устроено. Лучше не рискуйте, берите билет и езжайте спокойно, к тому же стоит он совсем не дорого. (На фото, как видите, один билет не прокомпостирован снизу).</p>

<a href="javascript:return false;" title="" class="shutterset_singlepic71" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/71__x_dsc_5823.jpg" alt="dsc_5823" title="dsc_5823" />
</a>

<p>Метро в Праге состоит из 3х линий: зеленая линия А, желтая B и красная C. Černý Most — это конечная станция желтой линии. Когда мы, уже на следующий день, возвращались мы проехали одну станцию по красной линии, а на зеленой так и не побывали. На красной линии нам попался поезд поновее, сидения там были мягче, а двери открывались как в автобусе, немного выезжая вперед. </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic73" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/73__x_dsc_5829.jpg" alt="dsc_5829" title="dsc_5829" />
</a>

<p>На желтой же, поезда хотя и не выглядели старыми, были чуть попроще. С виду такие же, как в Санкт-Петербурге, только переоборудованные внутри. Над дверьми располагается лампочка, которая загорается красным, когда дверь закрывается, естественно при этом еще и предупреждают по-чешски.</p>

<a href="javascript:return false;" title="" class="shutterset_singlepic74" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/74__x_dsc_5830.jpg" alt="dsc_5830" title="dsc_5830" />
</a>

<p>Вестибюли метро довольно простые, похожи на некоторые из самых невзрачных петербургских станций. Эскалатор такой же как в Петербурге, только без ламп посреди баллюстрады.</p>
<p>
<a href="javascript:return false;" title="" class="shutterset_singlepic77" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/77__x_dsc_5860.jpg" alt="dsc_5860" title="dsc_5860" />
</a>
<br />

<a href="javascript:return false;" title="" class="shutterset_singlepic79" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/79__x_dsc_5867.jpg" alt="dsc_5867" title="dsc_5867" />
</a>
</p>
<p>На метро мы приехали на станцию Náměstí Republiky. Регистрироваться в отеле можно было с 2х часов дня, а было, я напомню, всего 11, поэтому мы пошли гулять. Нас сразу впечатлила Пороховая башня (Prašná brána) и мы захотели поднятся на нее. Внутри была довольно длинная винтовая лестница и подниматься порядком утомило. </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic82" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/82__x_dsc_5875.jpg" alt="dsc_5875" title="dsc_5875" />
</a>

<p>Сперва поднялись до первого внутреннего зала, где стояли доспехи рыцаря, разное оружие старых времени, старинные книги на чешском и все такое прочее. Вместо окон в башне почти везде были витражи. В этом же зале надо платить за вход, по-моему что-то около 100 крон (4 евро). Дальше опять подъем по винтовой лестнице и еще один зал, теперь со сценой средневековой битвы. И наконец, последнее усилие, и мы наверху. </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic84" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/84__x_dsc_5922_stitch.jpg" alt="dsc_5922_stitch" title="dsc_5922_stitch" />
</a>

<p>Открывается красивый вид на Прагу. Проход там наверху очень узкий и фотографировать друг друга на фоне города трудно, к тому же окошки не очень большие. То есть это место скорее из разряда посмотреть, чем пофотографировать, но я думаю, что своих денег оно в любом случае стоит. Спускались мы сразу все три части лестницы и голова порядком закружилась.</p>

<a href="javascript:return false;" title="" class="shutterset_singlepic85" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/85__x_dsc_5976.jpg" alt="dsc_5976" title="dsc_5976" />
</a>

<p>Дальше наш путь лежал по Целетной улице (Celetná ulice) до очень красивой Староместской площади (Staroměstské náměstí). На самой площади, конечно, было множество народу. На вертелах жарились большие куски свинины и заманчиво пахли. Стоит это удовольствие 85 крон (3 евро) за 100 граммов и мы решили лучше потерпеть потом до ресторана. Так же на площади происходило какое-то событие, была сцена и большой экран, передающий события на сцене. Выступал этнический коллектив с немецкими песнями. </p>
<p>
<a href="javascript:return false;" title="" class="shutterset_singlepic86" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/86__x_dsc_5981_stitch.jpg" alt="dsc_5981_stitch" title="dsc_5981_stitch" />
</a>
<br />

<a href="javascript:return false;" title="" class="shutterset_singlepic87" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/87__x_dsc_5987.jpg" alt="dsc_5987" title="dsc_5987" />
</a>
</p>
<p>Спонсором, видимо, была марка машин Hyundai, потому что сцена и экран, и еще какие-то инсталляции были облеплены логотипами. Чуть-чуть послушали и пошли дальше. Мимо астрономических часов, рядом с которыми толпились люди. Оказалось, что времени было без десяти час, а в час что-то должно было произойти. И произошло. Фигурки рядом с часами задвигались: </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic89" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/89__x_dsc_6262.jpg" alt="dsc_6262" title="dsc_6262" />
</a>

<p>скелет дергал за веревочку и тем самым звонил в колокол, фигура турка (как мы услышали у экскурсовода неподалеку) трясла палкой, с другой стороны часов фигурка лицемерия смотрелась в зеркало, а «жадность» трясла мешком с деньгами. Потом золотой петух над часами прокукарекал, с верхнего этаже здания с часами высунулся трубач и протрубил мелодию. Такое вот небольшое представление. Мы пошли дальше по улице до Карлового моста (Karlův most) через Влтаву. На мосту тоже было много народу, идти приходилось почти проталкиваясь. На перилах были скульптуры, играла какая-то группа и продавала диски, художники предлагали картины, фотографии. На другой стороне моста мы поняли, что уже порядком устали и проголодались. </p>

<a href="javascript:return false;" title="" class="shutterset_singlepic88" >
	<img class="ngg-singlepic ngg-center" src="http://www.charnad.com/blog/wp-content/gallery/cache/88__x_dsc_6025.jpg" alt="dsc_6025" title="dsc_6025" />
</a>

<p>В мои планы входило прогуляться дальше, я не расчитывал что мы так сильно захотим есть в это время, и не искал ресторанов в том районе. Поэтому решили идти в McDonald's, это было проще всего. Когда покушали, время уже перевалило за 2 часа, поэтому мы отправились в отель.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/poezdka-v-czechiu-part-1/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/poezdka-v-czechiu-part-1/</feedburner:origLink></item>
		<item>
		<title>Symfony: выборочная I18n для объектов Doctrine [Перевод]</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/6JPKxc5zvhs/</link>
		<comments>http://www.charnad.com/blog/symfony-vyborochnaya-i18n-dlya-obektov-doctrine/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 00:44:59 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[I18n]]></category>
		<category><![CDATA[symfony]]></category>
		<category><![CDATA[перевод]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1085</guid>
		<description><![CDATA[Мне потребовалось сделать мультиязычный сайт аж на 5 языках. В целом тут нет ничего сложного, кроме того, что пользователю надо будет заполнять 5 форм на разных языках. Логичный вывод - сделать обязательным только один язык, например английский. Остальные заполняются по желанию, а для незаполненных показывается на том же английском. Промучившись некоторое время с рецептами от [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/symfony_logo.gif" alt="" />Мне потребовалось сделать мультиязычный сайт аж на 5 языках. В целом тут нет ничего сложного, кроме того, что пользователю надо будет заполнять 5 форм на разных языках. Логичный вывод - сделать обязательным только один язык, например английский. Остальные заполняются по желанию, а для незаполненных показывается на том же английском. Промучившись некоторое время с рецептами от Календаря Адвента, и не добившись успеха, я нашел пост [<a href="http://www.miximum.fr/tutos/449-optional-translation-form-for-i18n-objects-with-symfony-and-doctrine#comment-14308">Optional translation form for I18n objects with Symfony and Doctrine</a>], который мне помог. Я считаю, что полезным будет сделать его перевод. Так же я добавлю некоторые свои комментарии. (Перевод вольный, эстеты идут лесом)<span id="more-1085"></span></p>
<p>Некоторые люди утверждают, что Symfony - это подарок богов. Другие считают, что это преувеличение. Но как ни крути, в версиях 1.3/1.4 добавилось много нового и полезного, что может сэкономить вам вермя.<br />
Представим проект, где есть разные заметки (новости, интервью, и т.д.). И они могут быть на разных языках. И это довольно просто сделать с actAs: I18n. Но есть небольшая сложность: переводы должны быть опциональны, чтобы можно было написать статью только на французском, английском или немецком.
</p>
<p>Некоторые материалы по теме: <a href="http://prendreuncafe.com/blog/post/2009/11/29/Embedding-Relations-in-Forms-with-Symfony-1.3-and-Doctrine">раз</a>, <a href="http://symfonyguide.wordpress.com/2009/09/28/symfony-forms-saving-process/">два</a>, <a href="http://vousavezchoisi.com/img/formsdiagram.png">три</a>, <a href="http://www.symfony-project.org/more-with-symfony/1_4/en/06-Advanced-Forms#chapter_06_ignoring_embedded_forms">четыре</a>, <a href="http://www.ze-technology.com/2009/06/05/tests-fonctionnels-avec-symfony-gerer-lidentification/">пять</a>.</p>
<h3>Итак, начнем со схемы.</h3>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">Article:
  actAs:
    Timestampable: ~
    I18n:
      fields: [ title, body ]
      actAs:
        Sluggable: { fields: [ title ], uniqueBy: [ lang, title ] }
&nbsp;
  columns:
    title: { type: string(255), notnull: true }
    body: { type: clob, notnull: true }
    author: { type: string(255), notnull: false }
&nbsp;
News:
  inheritance:
    extends: Article
    type: concrete</pre></div></div>

<p>А так же фикстуры:</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;">News:
  n1:
    author: 'Lenta.ru'
    Translation:
      ru:
        title: 'Нет вестей с Титана'
        body: |
          Титан – это шестой и самый крупный спутник Сатурна.
&nbsp;
  n2:
    author: 'Bash.org'
    Translation:
      en:
        title: '#921792'
        body: |
          &lt;Thomas&gt; if women think they arent meant to cook
          &lt;Thomas&gt; why do they have milk and eggs inside them?</pre></div></div>

<p>Загружаем все это добро в базу данных:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">php symfony doctrine:build <span style="color: #660033;">--all</span> <span style="color: #660033;">--and-load</span>
php symfony generate:app backend
php symfony doctrine:generate-admin backend News</pre></div></div>

<p>Загляните в только что построенный модуль админки. Нажмите кнопку "редактировать" и оп.. а где все наши переводы? Если вы еще не в курсе, actAs:I18n разделяет таблицу на 2 части, в первой содержатся общие поля, не зависящие от перевода, а во второй те, которые требуют перевода.</p>

<div class="wp_syntax"><div class="code"><pre class="txt" style="font-family:monospace;">mysql&gt; SELECT * FROM news;
+----+-------------+---------------------+---------------------+
| id | author      | created_at          | updated_at          |
+----+-------------+---------------------+---------------------+
|  1 | Lenta.ru    | 2010-01-29 12:14:46 | 2010-01-29 12:14:46 | 
|  2 | Bash.org    | 2010-01-29 12:14:46 | 2010-01-29 12:14:46 | 
+----+-------------+---------------------+---------------------+
&nbsp;
mysql&gt; SELECT id, lang, title FROM news_translation;
+----+------+-----------------------------------------------------+
| id | lang | title                                               |
+----+------+-----------------------------------------------------+
|  1 | ru   | Титан – это шестой и самый крупный спутник Сатурна. | 
|  2 | en   | &lt;Thomas&gt; if women think they arent meant to cook ...| 
+----+------+-----------------------------------------------------+</pre></div></div>

<p>Чтобы нам было доступно редактирование переводов - надо воспользоваться функцией embedI18n.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// lib/form/doctrine/NewsForm.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> NewsForm <span style="color: #000000; font-weight: bold;">extends</span> BaseNewsForm
<span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * @see ArticleForm
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedI18n</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'ru'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'en'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Вуа ля. Редактировать можно!
</p>
<h3>Немного приберемся</h3>
<p>Наш код сейчас не так хорош, как мог бы быть:<br />
Каждый раз, когда мы будем добавлять новый тип статьи - нам надо будет менять метод configure;<br />
Каждый раз, когда мы будем добавлять/удалять новый язык для статей - нам надо будет менять все формы.</p>
<p>К счастью, с Symfony 1.3, наследование форм повторяет наследование моделей. Смотрите, NewsForm наследует BaseNewsForm, которая в свою очередь наследует ArticleForm.</p>

<div class="wp_syntax"><div class="code"><pre class="yml" style="font-family:monospace;"># config/app.yml
all:
  cultures:
    enabled:
      ru: Russian
      en: English</pre></div></div>


<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// lib/form/doctrine/NewsForm.class.php</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Revert the changes we added there</span>
<span style="color: #000000; font-weight: bold;">class</span> NewsForm <span style="color: #000000; font-weight: bold;">extends</span> BaseNewsForm
<span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * @see ArticleForm
   */</span>
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">configure</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// lib/form/doctrine/ArticleForm.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> ArticleForm <span style="color: #000000; font-weight: bold;">extends</span> BaseArticleForm
<span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * Available languages
   *
   * @var array $languages
   **/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$langages</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_cultures_enabled'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$langs</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedI18n</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$langs</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$lang</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$label</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$label</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Перезагрузите теперь страницу. Вы можете теперь добавлять/удалять языки независимо от количества типов статей.</p>
<h3>Редактируем переводы</h3>
<p>
Давайте теперь попробуем нашу форму для статей. Когда вы попробуете редактировать какую-нибудь новость, то... постыдная неудача. Нельзя сохранить, потому что нет английского или русского перевода. Давайте добавим условие, что если в форме есть пустые поля - мы эти формы не сохраняем.<br />
Для этого мы перекроем метод doBind.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// lib/form/doctrine/ArticleForm.class.php</span>
<span style="color: #000000; font-weight: bold;">class</span> ArticleForm <span style="color: #000000; font-weight: bold;">extends</span> BaseArticleForm
<span style="color: #009900;">&#123;</span>
  <span style="color: #009933; font-style: italic;">/**
   * Available languages
   *
   * @var array $languages
   **/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$langages</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> configure<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span> <span style="color: #339933;">=</span> sfConfig<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'app_cultures_enabled'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$langs</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array_keys</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embedI18n</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$langs</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$lang</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$label</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">widgetSchema</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLabel</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$label</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Cleans and binds values to the current form
   *
   * Ignore i18n forms when all their fields are empty
   *
   * @see sfForm::doBind
   **/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> doBind<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$lang</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$label</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embeddedI18nFormIsEmpty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span>
          <span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
          <span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    parent<span style="color: #339933;">::</span><span style="color: #004000;">doBind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #009933; font-style: italic;">/**
   * Check if every fields, except for id and lang, are empty
   **/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> embeddedI18nFormIsEmpty<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$key</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">in_array</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$key</span><span style="color: #339933;">,</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'id'</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'lang'</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
        <span style="color: #b1b100;">continue</span><span style="color: #339933;">;</span>
&nbsp;
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">''</span> <span style="color: #339933;">!==</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>В перекрытом методе doBind, мы проверяем каждую I18n форму, и, если надо делаем ей unset. Теперь все сохраняется как надо, однако же...</p>
<p>Загляните в базу данных, вас там ждет сюрприз.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">SELECT</span> id<span style="color: #66cc66;">,</span> lang<span style="color: #66cc66;">,</span> slug <span style="color: #993333; font-weight: bold;">FROM</span> news_translation;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+------+------------------------------------------------------+</span>
<span style="color: #66cc66;">|</span> id <span style="color: #66cc66;">|</span> lang <span style="color: #66cc66;">|</span> slug                                                 <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+------+------------------------------------------------------+</span>
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> en   <span style="color: #66cc66;">|</span>                                                      <span style="color: #66cc66;">|</span> 
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">1</span> <span style="color: #66cc66;">|</span> ru   <span style="color: #66cc66;">|</span> Титан – это шестой и самый крупный спутник Сатурна<span style="color: #66cc66;">.</span>  <span style="color: #66cc66;">|</span> 
<span style="color: #66cc66;">|</span>  <span style="color: #cc66cc;">2</span> <span style="color: #66cc66;">|</span> en   <span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&lt;</span>Thomas<span style="color: #66cc66;">&gt;</span> <span style="color: #993333; font-weight: bold;">IF</span> women think they arent meant <span style="color: #993333; font-weight: bold;">TO</span> cook <span style="color: #66cc66;">...</span> <span style="color: #66cc66;">|</span> 
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">----+------+------------------------------------------------------+</span></pre></div></div>

<p>Где-то в процессе сохранения, Symfony создала пустой объект перевода. И вот решение для этой проблемы.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">// lib/form/doctrine/ArticleForm.class.php</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// Add this at the beginnig of the class:</span>
  <span style="color: #009933; font-style: italic;">/**
   * I18n ignored forms
   **/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000088;">$I18nFormsIgnored</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// update the doBind method:</span>
  <span style="color: #009933; font-style: italic;">/**
   * Unset i18n forms values when every field is empty
   **/</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> doBind<span style="color: #009900;">&#40;</span><span style="color: #990000;">array</span> <span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">languages</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$lang</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$label</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">embeddedI18nFormIsEmpty</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span>
      <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">I18nFormsIgnored</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$lang</span><span style="color: #339933;">;</span>
        <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span>
          <span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span>
          <span style="color: #000088;">$this</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span>
        <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    parent<span style="color: #339933;">::</span><span style="color: #004000;">doBind</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// And override the doUpdateObject method:</span>
  <span style="color: #009933; font-style: italic;">/**
   * Updates the values of the object with the cleaned up values.
   *
   * @param  array $values An array of values
   *
   * @see sfFormDoctrine::doUpdateObject()
   */</span>
  <span style="color: #000000; font-weight: bold;">protected</span> <span style="color: #000000; font-weight: bold;">function</span> doUpdateObject<span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span>
  <span style="color: #009900;">&#123;</span>
    parent<span style="color: #339933;">::</span><span style="color: #004000;">doUpdateObject</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">I18nFormsIgnored</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$lang</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
      <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">object</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">Translation</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #990000;">unset</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$values</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$lang</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>На этот раз все сохраняется как надо!
</p>
<p>(Здесь я пропускаю абзац про убирание поля Slug. Там есть сложность с тем, что формы перевода не наследуются. Если вам интересно - посмотрите в оригинальной статье. Я считаю, что основное здесь - как раз перекрытие методов doBind и doUpdateObject.<br />
Тесты, приведенные автором можно посмотреть у него в статье, а можно <a href="http://pastie.org/995806">тут</a> и <a href="http://pastie.org/995807">тут</a>).</p>
<p>На этом все. Надеюсь вам пригодится мой перевод.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/symfony-vyborochnaya-i18n-dlya-obektov-doctrine/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/symfony-vyborochnaya-i18n-dlya-obektov-doctrine/</feedburner:origLink></item>
		<item>
		<title>Python: играем с PyGame. Начало.</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/MlTGAaKBf3A/</link>
		<comments>http://www.charnad.com/blog/python-igraem-s-pygame-nachalo/#comments</comments>
		<pubDate>Tue, 27 Apr 2010 15:51:03 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[gamedev]]></category>
		<category><![CDATA[pygame]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1062</guid>
		<description><![CDATA[В этом блоге почти все время я писал о PHP и немного о JS. Настало время разнообразить, и разнообразить свой блог я решил Питоном. О том, где взять Python и где поучиться я не буду, материалов полно, и большинство друг друга повторяют, в еще одном от меня смысла я не вижу. Чуть меньше примеров и [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/python_logo.png" alt="" style="float: left; padding-right: 5px;"/>
<p>В этом блоге почти все время я писал о PHP и немного о JS. Настало время разнообразить, и разнообразить свой блог я решил Питоном. О том, где <a href="http://python.org/">взять Python</a> и где <a href="http://diveintopython.org/">поучиться</a> я не буду, материалов полно, и большинство друг друга повторяют, в еще одном от меня смысла я не вижу. Чуть меньше примеров и статей про <a href="http://www.pygame.org">PyGame</a> - свободную графическую библиотеку, базирующуюся на SDL.</p>
<p><span id="more-1062"></span></p>
<p>Проблем с установкой, я надеюсь у вас не возникнет - либо запускате Windows инсталлер, а если вы в Linux - наверняка сами знаете. Не будем тянуть кота за хвост, откроем IDE, создадим проект и уже создадим хотя бы окошко.<br />
<strong>main.py</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #ff7700;font-weight:bold;">import</span> pygame
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Game<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#Initial window settings</span>
        pygame.<span style="color: black;">init</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        pygame.<span style="color: black;">display</span>.<span style="color: black;">set_mode</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">640</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">480</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        pygame.<span style="color: black;">display</span>.<span style="color: black;">set_caption</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'I<span style="color: #000099; font-weight: bold;">\'</span>m super cool Python programmer'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">#Run, Forrest, run</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">track_input</span><span style="color: black;">&#40;</span>pygame.<span style="color: black;">event</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> track_input<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> events<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> event <span style="color: #ff7700;font-weight:bold;">in</span> events:
            <span style="color: #808080; font-style: italic;">#Exit</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: #008000;">type</span> <span style="color: #66cc66;">==</span> pygame.<span style="color: black;">QUIT</span>:
                exit<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">#Here we go</span>
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    Game<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Сохраняете, запускаете, смотрите. Опа, окошечко. И даже закрывается по крестику. Теперь обьясню как это произошло. Сначала нам нужно импортировать pygame, иначе ничего не получится. Запуск скрипта начинается с последних строчек, которые создают экземпляр класса Game. Такая конструкция с переменной __name__ требуется для того, чтобы при импорте этой программы она не запускалась, а срабатывала только если файл запущен непосредственно. Функция __init__  в классе Game является чем-то вроде конструктора (но не конструктором!). Она вызывает метод pygame.init(), который инициализирует библиотеку, дальше вызываем метод pygame.display.set_mode((640, 480)), который и создает собственно окно размером 640х480. Обратите внимание, мы передаем кортеж, а не просто 2 числа. Дальше даем окну заголовок. На этом можно было бы и остановиться, программа уже будет работать. Но окно выскочит и закроется, потому что программа завершится. Чтобы этого не произошло запускаем функцию run(), которая представляет из себя бесконечный цикл вызовов функции track_input, которая принимает параметром события. И если произошло событие "Выход" (то самое нажатие по крестику), то закрываем. Все можно было бы уместить в одну функцию, но это задел на будущее.</p>
<p>Что же нам хочется дальше? Конечно же, чтобы что-то двигалось по стрелочкам. Почти в любой игре что-нибудь надо двигать, и у нас не будет исключение. Что же нужно? Нужно все так же следить за событиями, только теперь обрабатывать нажатия на кнопки стрелок. Чтобы удобнее было использовать направления (вверх, вправо, вниз, влево) обозначим их цифрами 0, 1, 2, 3. А чтобы не запутаться, введем переменные UP, RIGHT, DOWN, LEFT, которым и дадим эти значения. А переменные положим в отдельный файл directions.py и наступит ваще красота.<br />
<strong>directions.py</strong></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    exit<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
&nbsp;
UP    <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
RIGHT <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
DOWN  <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">2</span>
LEFT  <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">3</span>
DIRECTIONS <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>UP<span style="color: #66cc66;">,</span> RIGHT<span style="color: #66cc66;">,</span> DOWN<span style="color: #66cc66;">,</span> LEFT<span style="color: black;">&#93;</span>
VERTICAL <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>UP<span style="color: #66cc66;">,</span> DOWN<span style="color: black;">&#93;</span>
HORIZONTAL <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>LEFT<span style="color: #66cc66;">,</span> RIGHT<span style="color: black;">&#93;</span></pre></div></div>

<p>Обьявили наши переменные и три списка, которые нам пригодятся в будущем. Вернемся в main.py. Добавим к списку импортов directions.py:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> directions</pre></div></div>

<p>В класс Game добавим словарь и 3 переменные:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">x <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
y <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
speed <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">3</span>
&nbsp;
keymap <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
    pygame.<span style="color: black;">K_LEFT</span>  : directions.<span style="color: black;">LEFT</span><span style="color: #66cc66;">,</span>
    pygame.<span style="color: black;">K_UP</span>    : directions.<span style="color: black;">UP</span><span style="color: #66cc66;">,</span>
    pygame.<span style="color: black;">K_RIGHT</span> : directions.<span style="color: black;">RIGHT</span><span style="color: #66cc66;">,</span>
    pygame.<span style="color: black;">K_DOWN</span>  : directions.<span style="color: black;">DOWN</span>
<span style="color: black;">&#125;</span></pre></div></div>

<p>Три переменные будут отвечать за положение и скорость перемещения объекта. А словарь ставит в соответствие клавиши и направления. Я надеюсь, что очевидно, что когда мы будем нажимать на какую-то кнопку, благодаря этому словарю мы узнаем в каком направлении надо двигать наш игровой объект, из положения x,y на speed пикселей. Далее в track_input добавляем в цикл:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: #008000;">type</span> <span style="color: #66cc66;">==</span> pygame.<span style="color: black;">KEYDOWN</span> <span style="color: #ff7700;font-weight:bold;">and</span> event.<span style="color: black;">key</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">keymap</span>.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">keymap</span><span style="color: black;">&#91;</span>event.<span style="color: black;">key</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">in</span> directions.<span style="color: black;">DIRECTIONS</span>:
    <span style="color: #008000;">self</span>.<span style="color: black;">move</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">keymap</span><span style="color: black;">&#91;</span>event.<span style="color: black;">key</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Здесь мы проверяем, что нажата кнопка (нажатия мышки и т.п. нас сейчас не интересуют) и что кнопка указана среди keymap, и то, что по выбранной кнопке в keymap стоит нормальное направление. И если все в порядке - вызываем функцию move с параметром "направление" из словаря.<br />
В Python, насколько я знаю, нету операции switch/case, поэтому здесь мы будем делать финт ушами. Вот функция move, которую мы кладем все в тот же класс Game:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> move<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> direction<span style="color: black;">&#41;</span>:
    movement <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
        directions.<span style="color: black;">UP</span>       : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span>            <span style="color: #008000;">self</span>.<span style="color: black;">y</span>-<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        directions.<span style="color: black;">RIGHT</span>  : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span>+<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        directions.<span style="color: black;">DOWN</span>  : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span>            <span style="color: #008000;">self</span>.<span style="color: black;">y</span>+<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
        directions.<span style="color: black;">LEFT</span>    : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span>-<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span><span style="color: black;">&#93;</span>
    <span style="color: black;">&#125;</span>
    <span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span> <span style="color: #66cc66;">=</span> movement<span style="color: black;">&#91;</span>direction<span style="color: black;">&#93;</span></pre></div></div>

<p>Здесь у нас словарь с направлениями, по которым лежат списки с изменением параметров x и y, и когда вызывается нужное направление с помощью множественного присваивания мы изменяем сразу x и y.<br />
Ну и наконец, в run() добавляем код, который будет рисовать нам маленький беленький квадратик, который и будет двигаться от наших нажатых кнопок.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">pygame.<span style="color: black;">display</span>.<span style="color: black;">get_surface</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">fill</span><span style="color: black;">&#40;</span>pygame.<span style="color: black;">Color</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
block <span style="color: #66cc66;">=</span> pygame.<span style="color: black;">Surface</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
block.<span style="color: black;">fill</span><span style="color: black;">&#40;</span>pygame.<span style="color: black;">Color</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">255</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">255</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">255</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
pygame.<span style="color: black;">display</span>.<span style="color: black;">get_surface</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">blit</span><span style="color: black;">&#40;</span>block<span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
pygame.<span style="color: black;">display</span>.<span style="color: black;">flip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Давайте теперь посмотрим что у нас получилось.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#! /usr/bin/python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
<span style="color: #ff7700;font-weight:bold;">import</span> pygame
<span style="color: #ff7700;font-weight:bold;">import</span> directions
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Game<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
&nbsp;
    x <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
    y <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">100</span>
    speed <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">3</span>
&nbsp;
    keymap <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
        pygame.<span style="color: black;">K_LEFT</span>  : directions.<span style="color: black;">LEFT</span><span style="color: #66cc66;">,</span>
        pygame.<span style="color: black;">K_UP</span>    : directions.<span style="color: black;">UP</span><span style="color: #66cc66;">,</span>
        pygame.<span style="color: black;">K_RIGHT</span> : directions.<span style="color: black;">RIGHT</span><span style="color: #66cc66;">,</span>
        pygame.<span style="color: black;">K_DOWN</span>  : directions.<span style="color: black;">DOWN</span>
    <span style="color: black;">&#125;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;">#Initial window settings</span>
        pygame.<span style="color: black;">init</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        pygame.<span style="color: black;">display</span>.<span style="color: black;">set_mode</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">640</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">480</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        pygame.<span style="color: black;">display</span>.<span style="color: black;">set_caption</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'I<span style="color: #000099; font-weight: bold;">\'</span>m super cool Python programmer'</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
            <span style="color: #008000;">self</span>.<span style="color: black;">track_input</span><span style="color: black;">&#40;</span>pygame.<span style="color: black;">event</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            pygame.<span style="color: black;">display</span>.<span style="color: black;">get_surface</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">fill</span><span style="color: black;">&#40;</span>pygame.<span style="color: black;">Color</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            block <span style="color: #66cc66;">=</span> pygame.<span style="color: black;">Surface</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            block.<span style="color: black;">fill</span><span style="color: black;">&#40;</span>pygame.<span style="color: black;">Color</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">255</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">255</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">255</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            pygame.<span style="color: black;">display</span>.<span style="color: black;">get_surface</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">blit</span><span style="color: black;">&#40;</span>block<span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
            pygame.<span style="color: black;">display</span>.<span style="color: black;">flip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> track_input<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> events<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> event <span style="color: #ff7700;font-weight:bold;">in</span> events:
            <span style="color: #808080; font-style: italic;">#Exit</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: #008000;">type</span> <span style="color: #66cc66;">==</span> pygame.<span style="color: black;">QUIT</span>:
                exit<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> event.<span style="color: #008000;">type</span> <span style="color: #66cc66;">==</span> pygame.<span style="color: black;">KEYDOWN</span> <span style="color: #ff7700;font-weight:bold;">and</span> event.<span style="color: black;">key</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">self</span>.<span style="color: black;">keymap</span>.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">keymap</span><span style="color: black;">&#91;</span>event.<span style="color: black;">key</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">in</span> directions.<span style="color: black;">DIRECTIONS</span>:
                <span style="color: #008000;">self</span>.<span style="color: black;">move</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">keymap</span><span style="color: black;">&#91;</span>event.<span style="color: black;">key</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> move<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> direction<span style="color: black;">&#41;</span>:
        movement <span style="color: #66cc66;">=</span> <span style="color: black;">&#123;</span>
            directions.<span style="color: black;">UP</span> : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span>            <span style="color: #008000;">self</span>.<span style="color: black;">y</span>-<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
            directions.<span style="color: black;">RIGHT</span> : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span>+<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
            directions.<span style="color: black;">DOWN</span> : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span>            <span style="color: #008000;">self</span>.<span style="color: black;">y</span>+<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
            directions.<span style="color: black;">LEFT</span> : <span style="color: black;">&#91;</span><span style="color: #008000;">self</span>.<span style="color: black;">x</span>-<span style="color: #008000;">self</span>.<span style="color: black;">speed</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span><span style="color: black;">&#93;</span>
        <span style="color: black;">&#125;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">x</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">y</span> <span style="color: #66cc66;">=</span> movement<span style="color: black;">&#91;</span>direction<span style="color: black;">&#93;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:
    Game<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Запускаем, и... видим маленький беленький квадратик, который двигается когда мы тыкаем стрелочки. Хотелось бы плавные движения пока нажата клавиша, правда? Но об этом в другой раз.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/python-igraem-s-pygame-nachalo/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/python-igraem-s-pygame-nachalo/</feedburner:origLink></item>
		<item>
		<title>Исходники судоку</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/gZbp_2tcZus/</link>
		<comments>http://www.charnad.com/blog/isxodniki-sudoku/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 19:30:46 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[sources]]></category>
		<category><![CDATA[sudoku]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=1005</guid>
		<description><![CDATA[Я уже давно обещал выложить исходные коды судоку (поиграйте в судоку, если еще не играли). Я думал, что со временем исправлю код, сделаю лучше, но нет ни времени, ни желания. Поэтому лучше я выложу как есть, а вы уж сами улучшайте. Посмотреть код. Далее в посте будут комментарии. Что касается алгоритма, то здесь все работает [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" style="float:left;" src="http://www.charnad.com/blog/wp-content/uploads/pictures/php.gif" alt=""/> Я уже давно обещал выложить исходные коды судоку (<a href="http://www.charnad.com/blog/sudoku-na-php-i-jquery/">поиграйте в судоку</a>, если еще не играли). Я думал, что со временем исправлю код, сделаю лучше, но нет ни времени, ни желания. Поэтому лучше я выложу как есть, а вы уж сами улучшайте. <a href="https://gist.github.com/e847effbb99ee94fc37a">Посмотреть код</a>. Далее в посте будут комментарии.<span id="more-1005"></span></p>
<p>Что касается алгоритма, то здесь все работает так. У нас есть поле 9х9, соответственно начнем мы с</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> generate<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error_counter</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
  <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$row</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">9</span><span style="color: #339933;">;</span> <span style="color: #000088;">$row</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$col</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$col</span> <span style="color: #339933;">&lt;</span> <span style="color: #cc66cc;">9</span><span style="color: #339933;">;</span> <span style="color: #000088;">$col</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span></pre></div></div>

<p>$error_counter служит нам для защиты от тупиков. Сейчас вы увидите о чем речь.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error_counter</span> <span style="color: #339933;">&gt;</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">retry_after</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//Row will be incremented to 0</span>
    <span style="color: #000088;">$row</span> <span style="color: #339933;">=</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$col</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error_counter</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">reset</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Если количество ошибок при генерации вышло за определенные пределы - значит звезды сложились неудачно и что-то где-то не сходится. Поэтому генерация сбрасывается и начинается заново.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sudoku</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$col</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getNum</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">//Вычисляем какие цифры подходят в текущую клетку</span>
    <span style="color: #000088;">$fit</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">fit</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$row</span><span style="color: #339933;">,</span> <span style="color: #000088;">$col</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #000088;">$percents</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #000088;">$numbers</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$number</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$percents</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$number</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">percentage</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$number</span><span style="color: #339933;">,</span> <span style="color: #000088;">$row</span><span style="color: #339933;">,</span> <span style="color: #000088;">$col</span><span style="color: #339933;">,</span> <span style="color: #000088;">$fit</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">//Here we get all numbers, that are most possible</span>
    <span style="color: #000088;">$available</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000088;">$max</span> <span style="color: #339933;">=</span> <span style="color: #990000;">max</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">array_values</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$percents</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$fit</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$number</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$percents</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$number</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">==</span> <span style="color: #000088;">$max</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000088;">$available</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$number</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Вот тут и происходит вся магия. Сначала вычисляем какие числа могут встать в клетку (смотрим, чтобы по вертикали, горизонтали и в малом квадрате такой не было). Далее для каждого из этих чисел запускается мутная функция percentage. Она вычисляет, какой шанс у числа попасть в эту клетку. Допустим у нас осталось 4 свободные клетки и 4 числа. При этом первое число может попасть в 1 клетку из 4х, второе в две, третье в три, четвертое во все. Эта функция просто делит количество клеток куда число может попасть на количество пустых клеток. Таким образом, выпадет число, у которого меньше всего шансов попасть в другие клетки. При равенстве берем случайное.
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//It can turn that sudoku generation isn't going well</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$available</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">==</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sudoku</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#93;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$cell</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$cell</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNum</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000088;">$row</span><span style="color: #339933;">--;</span>
    <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error_counter</span><span style="color: #339933;">++;</span>
    <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>В переменной available хранятся те самые числа, которые могут попасть в текущую клетку и имеют наивысшую вероятность попасть. Если вдруг оказывается, что никакое число не может попасть, а ряд еще не закончился - то мы сбрасываем текущий ряд и начинаем генерировать его заново. Ну а если сбрасывается ряд (по умолчанию) 30 раз, тогда, как я уже говорил, перегенерируется вся головоломка.
</p>
<p>
<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">error_counter</span> <span style="color: #339933;">&gt;</span> <span style="color: #000000; font-weight: bold;">self</span><span style="color: #339933;">::</span><span style="color: #004000;">retry_after</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">break</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">sudoku</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$row</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#91;</span><span style="color: #000088;">$col</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setNum</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$available</span><span style="color: #009900;">&#91;</span><span style="color: #990000;">mt_rand</span><span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #339933;">,</span> <span style="color: #990000;">count</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$available</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Тут все просто, если надо сбросить головоломку - идем в начало и сбрасываем. А если все в порядке - берем случайное число, если их несколько.<br />
Ну а все остальное по-моему достаточно просто и понятно.</p>
<p>That's all folks.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/isxodniki-sudoku/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/isxodniki-sudoku/</feedburner:origLink></item>
		<item>
		<title>PHP: эксклюзивный счетчик в Shared Memory</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/C2tlSg9C5b8/</link>
		<comments>http://www.charnad.com/blog/php-eksklyuzivnyj-schetchik-v-shared-memory/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 12:41:14 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[ipc]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[shared memory]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=992</guid>
		<description><![CDATA[Я надеюсь что вы уже прочитали вводную статью про многопоточность в PHP, или вам это просто не требуется. Теперь я расскажу про счетчик, который будет доступен для потоков приложения, при этом доступ к нему будет эксклюзивным. Разделяемая память - особая область памяти, которая доступа ВСЕМ процессам операционной системы. Доступ к определенному сегменту можно получить с [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" style="float:left;" src="http://www.charnad.com/blog/wp-content/uploads/pictures/php.gif" alt=""/></p>
<p>Я надеюсь что вы уже прочитали вводную статью про <a href="http://www.charnad.com/blog/mnogopotochnost-na-php/">многопоточность в PHP</a>, или вам это просто не требуется. Теперь я расскажу про счетчик, который будет доступен для потоков приложения, при этом доступ к нему будет эксклюзивным.</p>
<p><span id="more-992"></span></p>
<p>Разделяемая память - особая область памяти, которая доступа ВСЕМ процессам операционной системы. Доступ к определенному сегменту можно получить с помощью двух параметров: имени существующего файла и одного символа, который будет ключом System V IPC. Это нужно для того, чтобы несколько сегментов могли быть выделены основываясь на одном и том же файле. Звучит пока очень туманно, но сейчас я приведу пример, и надеюсь все станет понятно.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$t_key</span> <span style="color: #339933;">=</span> <span style="color: #990000;">ftok</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'g'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000088;">$shmid</span> <span style="color: #339933;">=</span> <span style="color: #990000;">shmop_open</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$t_key</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'c'</span><span style="color: #339933;">,</span> <span style="color: #208080;">0755</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">64</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">shmop_write</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$shmid</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">shmop_close</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$shmid</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Первой командой, специальной функцией ftok мы получили ключ, по которому будем получать доступ к сегменту разделяемой памяти. Первым параметром мы передали ему имя файла скрипта, а вторым букву 'g'. Почему 'g'? А просто так, можно взять любой символ.<br />
Во второй строке мы собственно открываем доступ к сегменту памяти. Первый параметр - наш ключ, второй параметр 'c' - флаг указывающий на то, что мы создаем сегмент памяти, при том, если он уже существуем - он открывается на чтение/запись. Третий параметр - права на доступ, четвертый - размер в байтах.<br />
В третьей строке мы записываем туда единицу, последний параметр - смещение.<br />
И наконец закрываем сегмент.<br />
Теперь по адресу, который определяется файлом скрипта и буквой 'g' в сегменте размером 64 байта лежит единица, и ее может достать любой процесс.</p>
<p>Теперь представим, что у нас программа работает в 50 потоков, она обрабатывает файл строчка за строчкой. Мы не хотим, чтобы программа два раза обрабатывала одну строку, поэтому кладем в разделяемую память номер строки, которая была обработана последней. И каждый процесс перед тем, как считать строчку берет из разделяемой памяти номер последней обработанной строки, прибавляет единицу, записывает обратно в разделяемую память и идет обрабатывать эту строчку. Следующий процесс возьмет уже строчку с номером на один больше. Все хорошо, все радуются, работает быстро. Однако случается так, что два процесса одновременно решили взять значение из памяти и взяли одинаковое значение и записали одинаковое. А представьте, что сразу 50 процессов одновременно считают значение. В общем дело ясное, что нам надо ограничить доступ к памяти одним процессом.</p>
<p>Как раз для таких случаев придуманы семафоры. Семафор (semaphore) - это такая сущность, которая позволяет ограниченному количеству процессов одновременно получать "зеленый свет" на выполнение чего-либо. Семафор, у которого такое количество равно 1 называется мьютексом (mutex). Именно мьютекс позволит нам не допускать в наш сегмент памяти больше одного процесса и остановит анархию.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$sem</span> <span style="color: #339933;">=</span> <span style="color: #990000;">sem_get</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">ftok</span><span style="color: #009900;">&#40;</span><span style="color: #009900; font-weight: bold;">__FILE__</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'g'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #990000;">sem_acquire</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sem</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//тут может быть только один процесс</span>
<span style="color: #990000;">sem_release</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$sem</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Мы получаем ключ для семафора точно таким же образом, как и для разделяемой памяти. Третий параметр - автоматическое "отпускание" семафора, если поток, который был впущен завершился. Те потоки, которые попытаются получить доступ к семафору, будут блокированы до тех пор, пока семафор не освободится. Это похоже на очередь в туалет. Один внутри, остальные снаружи. Один выходит, другой заходит и закрывается, другие продолжают ждать.
</p>
<p>Таким образом, создав ячейку памяти и создав семафор мы получаем счетчик, который позволит нам обрабатывать файл построчно не боясь, что одна строка будет обработана два раза. Для использования этого принципа я сделал класс Counter, который работает в моем многопоточном приложении. Взять его можно <a href="http://pastebin.org/86576">вот здесь</a>. А тут я приведу пример использования:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Ноль это наше начальное состояние счетчика</span>
<span style="color: #000088;">$counter</span> <span style="color: #339933;">=</span> Counter<span style="color: #339933;">::</span>_new<span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'g'</span><span style="color: #339933;">,</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">//Порождаем потомков</span>
<span style="color: #b1b100;">for</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$i</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span> <span style="color: #000088;">$i</span> <span style="color: #339933;">&lt;</span> PROCESS_AMOUNT<span style="color: #339933;">;</span> <span style="color: #000088;">$i</span><span style="color: #339933;">++</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$pid</span> <span style="color: #339933;">=</span> pcntl_fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pid</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'Error spawning new process'</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">elseif</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pid</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">//Родительский процесс у нас ничего не будет делать</span>
    <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #666666; font-style: italic;">//Первый параметр - имя счетчика, и заодно часть ключа</span>
        <span style="color: #666666; font-style: italic;">//Второй параметр - увеличивать ли значение счетчика</span>
        <span style="color: #666666; font-style: italic;">//В данном случае мы просто читаем значение</span>
        <span style="color: #000088;">$counter</span> <span style="color: #339933;">=</span> Counter<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'g'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #666666; font-style: italic;">//TOTAL_LINES - количество строк в файле</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$counter</span> <span style="color: #339933;">&lt;</span> TOTAL_LINES<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">//Берем значение счетчика и увеличиваем его на 1</span>
            <span style="color: #000088;">$counter</span> <span style="color: #339933;">=</span> Counter<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'g'</span><span style="color: #339933;">,</span> <span style="color: #009900; font-weight: bold;">true</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #666666; font-style: italic;">//Обарабатываем файл</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/php-eksklyuzivnyj-schetchik-v-shared-memory/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/php-eksklyuzivnyj-schetchik-v-shared-memory/</feedburner:origLink></item>
		<item>
		<title>Многопоточность на PHP</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/1VkZs6lDkS8/</link>
		<comments>http://www.charnad.com/blog/mnogopotochnost-na-php/#comments</comments>
		<pubDate>Fri, 05 Feb 2010 12:05:36 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[*nix]]></category>
		<category><![CDATA[ipc]]></category>
		<category><![CDATA[linux]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=988</guid>
		<description><![CDATA[Хочу рассказать вам про многопоточные приложения, взаимодействие процессов (IPC) и применение всего этого на PHP. В качестве примера мы возьмем счетчик с эксклюзивным доступом, доступный для всех процессов. Что такое многопоточность? Это способ разделения программы на отдельные сущности (процессы и треды(threads)) для обеспечивания параллельности выполнения. Зачем это нужно? Для ускорения работы. Ведь открывая какой-нибудь сайт [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" style="float:left;" src="http://www.charnad.com/blog/wp-content/uploads/pictures/php.gif" alt=""/></p>
<p>Хочу рассказать вам про многопоточные приложения, взаимодействие процессов (IPC) и применение всего этого на PHP. В качестве примера мы возьмем счетчик с эксклюзивным доступом, доступный для всех процессов.</p>
<p><span id="more-988"></span></p>
<p>Что такое многопоточность? Это способ разделения программы на отдельные сущности (процессы и треды(threads)) для обеспечивания параллельности выполнения. Зачем это нужно? Для ускорения работы. Ведь открывая какой-нибудь сайт вы не хотите ждать пока сервер последовательно откроет его всем, кто запросил его до вас. Вы хотите сразу, поэтому сервер выделяет отдельный процесс или поток для обработки вашего запроса. </p>
<p>Сначала немного про многопточность в PHP. PHP не многопоточный язык, PHP не умеет работать с тредами. Однако мы можем использовать системные вызовы операционной системы для создания процессов. Это как если бы мы просто запускали PHP-CLI несколько раз. Основная команда pcntl_fork разделяет выполнение программы на 2 части: родительскую и дочернюю, при этом эта команда вернет идентификатор процесса. Если вернулся -1, значит произошла ошибка, если 0, значит мы в дочернем потоке, если число - значит в родительском. </p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$pid</span> <span style="color: #339933;">=</span> pcntl_fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pid</span> <span style="color: #339933;">==</span> <span style="color: #339933;">-</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #990000;">die</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Произошла ошибка'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$pid</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #666666; font-style: italic;">// Мы в родительском потоке</span>
     pcntl_wait<span style="color: #009900;">&#40;</span><span style="color: #000088;">$status</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//Ждем выполнения потомка</span>
<span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
     <span style="color: #666666; font-style: italic;">// Мы в потоке потомке</span>
     <span style="color: #666666; font-style: italic;">// Делаем что-нибудь</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>В этом примере мы разделили программу на 2 части. В родительском процессе мы ожидаем завершения дочернего, чтобы тот доложил об успешном завершении. В противном случае он останется висеть в системе, как процесс-зомби. А если мы хотим не 2 потока, а больше? Тогда вызываем pcntl_fork несколько раз.</p>
<p>Приведу пример, как можно использовать pcntl_fork для "демонизации" процесса. Демон (daemon) - процесс выполняющийся в фоновом режиме. Это бывает очень удобно для программ, которые выполняются долгое время и не требуют прямого общения с пользователем. В Windows службы - аналог демонов в *nix системах. Итак, у вас есть программа на PHP, выполняющаяся в командной строке и вы хотите, чтобы она работала в фоне. Конечно, вы всегда можете сделать так:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">nohup</span> php script.php <span style="color: #000000; font-weight: bold;">&amp;</span></pre></div></div>

<p>Это запустит вашу программу в фоновом режиме, а весь вывод будет перенаправлять в nohup.out. Более того, программа не завершится с выходом пользователя из системы. Но для демонов более правильный вариант создать процесс-потомок, закрыть родительский процесс (да-да, почти как зомби), только мы еще назначим наш дочерний поток "лидером сессии", то есть он сам сможет порождать дочерние потоки.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">//Demonization</span>
<span style="color: #000088;">$child_pid</span> <span style="color: #339933;">=</span> pcntl_fork<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #666666; font-style: italic;">// Если мы получили дочерний id, </span>
<span style="color: #666666; font-style: italic;">// то мы в родительском потоке</span>
<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$child_pid</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #990000;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">//Здесь мы уже в потомке, а родитель был закрыл</span>
<span style="color: #990000;">posix_setsid</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Таким образом мы получим независимо выполняющуюся программу. Завершить ее можно командой kill pid, где pid - идентификатор процесса. Тот самый, который возвращается в родительский поток и представляет собой целое неотрицательное число, уникальное в системе.
</p>
<p>Возникает вопрос, зачем же нужны threads, если есть процессы? Дело в том, что треды выполняются в том же контексте, что и породивший его процесс, то есть все треды имеют общие ресурсы, например открытые файлы. Закрыв файловый дескриптор в одном треде, вы получите ошибку в другом, если попытаетесь прочитать этот файл с тем же дескриптором. В свою очередь процессам нужен особый способ обмениваться данными, если вы хотите открыть один и тот же файл в разных процессах. Для такого общения есть множество инструментов. Один из основных - сигналы.</p>
<p>Сигналы - это системные вызовы, влияющие на поведение процессов. Сигнал может завершить, приостановить, или послать особый сигнал, определенный пользователем. Помимо сигналов есть разделяемая память (shared memory) и семафоры (semaphores). Более подробно о них, и вообще об устройстве posix совместимых операционных систем советую вам поискать в интернете. Это было краткое введение в тему, для подготовки к следующей статье про <a href="http://www.charnad.com/blog/php-eksklyuzivnyj-schetchik-v-shared-memory/">счетчик в shared memory</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/mnogopotochnost-na-php/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/mnogopotochnost-na-php/</feedburner:origLink></item>
		<item>
		<title>Модальное окно на jQuery blockUI</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/P1tJwHToNlM/</link>
		<comments>http://www.charnad.com/blog/modalnoe-okno-na-jquery-blockui/#comments</comments>
		<pubDate>Thu, 04 Feb 2010 18:53:35 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[JS]]></category>
		<category><![CDATA[blockUI]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[модальное окно]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=930</guid>
		<description><![CDATA[Создание модального диалога с помощью jquery плагина blockUI.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.charnad.com/blog/wp-content/uploads/pictures/blockui/blockui-modal.png" style="float: left; margin-right: 10px;">Я уже писал про создание модальных окон на jQuery с помощью Simplemodal, на этот раз я решил попробовать другой плагин и нашел для себя blockUI. Он потребует jQuery версии не ниже 1.2.3. Итак приступим.<span id="more-930"></span></p>
<p>Данные плагина:</p>
<ul>
<li>название: blockUI v2</li>
<li>размер: 15,6 кб без сжатия</li>
<li><a href="http://www.malsup.com/jquery/block/">сайт плагина</a>, <a href="http://github.com/malsup/blockui/raw/master/jquery.blockUI.js?v2.31">скачать</a>, <a href="http://www.malsup.com/jquery/block/#demos">демо</a></li>
</ul>
<p>На сайте разработчика он выглядит так:<br />
<img class="size-medium wp-image-79" src="http://www.charnad.com/blog/wp-content/uploads/pictures/blockui/blockui-demo.png" alt="" /></p>
<p>Для себя я подобрал определенные настройки, которые делают окна красивее. Во-первых, я хотел, чтобы модальное окно располагалось по центру экрана, а по умолчанию оно находится чуть левее. Во-вторых, я хотел сделать его похожим на модальные окна и дилалоги в Windows.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$.<span style="color: #660066;">blockUI</span>.<span style="color: #660066;">defaults</span>.<span style="color: #660066;">css</span>.<span style="color: #660066;">border</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'0px'</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//убираем серую границу</span>
$.<span style="color: #660066;">blockUI</span>.<span style="color: #660066;">defaults</span>.<span style="color: #660066;">fadeIn</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">100</span><span style="color: #339933;">;</span>  <span style="color: #006600; font-style: italic;">//ускоряем появление</span>
$.<span style="color: #660066;">blockUI</span>.<span style="color: #660066;">defaults</span>.<span style="color: #660066;">fadeOut</span> <span style="color: #339933;">=</span> <span style="color: #CC0000;">100</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//и исчезновение</span>
$.<span style="color: #660066;">blockUI</span>.<span style="color: #660066;">defaults</span>.<span style="color: #660066;">css</span>.<span style="color: #660066;">left</span> <span style="color: #339933;">=</span> <span style="color: #3366CC;">'40%'</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">//окно будет в центре</span></pre></div></div>

<p>Этот код нужно вставить в страницу после подключения плагина. Параметр left:40% зависит от ширины окна, в моем случае оно 275 пикселей.</p>
<p>Что же сделать, чтобы окно выглядело как в Windows? Я конечно не мастер верстки, но результат мне вполне подходит. Сначала делаем макет окна и даем ему стили.</p>

<div class="wp_syntax"><div class="code"><pre class="xml" style="font-family:monospace;"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;modal_dialog&quot;</span> <span style="color: #000066;">style</span>=<span style="color: #ff0000;">&quot;display:none; cursor: default&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;dialog&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;dialog_title_bar&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;dialog_caption&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>www.charnad.com<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;rotes_kreuz&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
  <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
   <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;dialog_pane&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Наше модальное окошко<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;div</span> <span style="color: #000066;">style</span>=<span style="color: #ff0000;">&quot;margin-top: 10px;&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;form</span> <span style="color: #000066;">action</span>=<span style="color: #ff0000;">&quot;&quot;</span> <span style="color: #000066;">method</span>=<span style="color: #ff0000;">&quot;POST&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span>
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;button&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;yes&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;Да&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;dialog_button&quot;</span><span style="color: #000000; font-weight: bold;">/&gt;</span></span>
       <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;input</span> <span style="color: #000066;">type</span>=<span style="color: #ff0000;">&quot;button&quot;</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;no&quot;</span> <span style="color: #000066;">value</span>=<span style="color: #ff0000;">&quot;Нет&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;close_dialog dialog_button&quot;</span> <span style="color: #000000; font-weight: bold;">/&gt;</span></span>
     <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/form<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
    <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
 <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/div<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></pre></div></div>

<p>Почему display: none? Потому что плагин автоматически переключит видимость. Теперь CSS:</p>

<div class="wp_syntax"><div class="code"><pre class="css" style="font-family:monospace;"><span style="color: #6666ff;">.dialog</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">cursor</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">default</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">border</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span> <span style="color: #993333;">solid</span> <span style="color: #cc00cc;">#000000</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #6666ff;">.dialog</span> form <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">margin</span><span style="color: #00AA00;">:</span> <span style="color: #933;">0px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Контейнер с заголовком */</span>
<span style="color: #6666ff;">.dialog</span> <span style="color: #6666ff;">.dialog_title_bar</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">17px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">background-image</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">dialog-caption-bg.png</span><span style="color: #00AA00;">&#41;</span> <span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Стиль текста заголовка */</span>
<span style="color: #6666ff;">.dialog</span> <span style="color: #6666ff;">.dialog_title_bar</span> <span style="color: #6666ff;">.dialog_caption</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">color</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">black</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">font-family</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">sans-serif</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">font-size</span><span style="color: #00AA00;">:</span> <span style="color: #933;">9pt</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">left</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">1px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Панель диалога */</span>
<span style="color: #6666ff;">.dialog</span> <span style="color: #6666ff;">.dialog_pane</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">background</span><span style="color: #00AA00;">:</span> buttonface<span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">text-align</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">center</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-left</span><span style="color: #00AA00;">:</span> <span style="color: #933;">10%</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-right</span><span style="color: #00AA00;">:</span> <span style="color: #933;">10%</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">10px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">padding-bottom</span><span style="color: #00AA00;">:</span> <span style="color: #933;">10px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Кнопки диалога */</span>
<span style="color: #6666ff;">.dialog</span> <span style="color: #6666ff;">.dialog_button</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">80px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">25px</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span>
&nbsp;
<span style="color: #808080; font-style: italic;">/* Красный крест, закрывающий окно */</span>
<span style="color: #6666ff;">.dialog</span> <span style="color: #6666ff;">.rotes_kreuz</span> <span style="color: #00AA00;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">background-image</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">url</span><span style="color: #00AA00;">&#40;</span><span style="color: #ff0000; font-style: italic;">rotes_kreuz.png</span><span style="color: #00AA00;">&#41;</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">width</span><span style="color: #00AA00;">:</span> <span style="color: #933;">28px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">height</span><span style="color: #00AA00;">:</span> <span style="color: #933;">15px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">position</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">absolute</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">right</span><span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">top</span><span style="color: #00AA00;">:</span> <span style="color: #933;">3px</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">float</span><span style="color: #00AA00;">:</span> <span style="color: #000000; font-weight: bold;">right</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">display</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">block</span><span style="color: #00AA00;">;</span>
    <span style="color: #000000; font-weight: bold;">cursor</span><span style="color: #00AA00;">:</span> <span style="color: #993333;">pointer</span><span style="color: #00AA00;">;</span>
<span style="color: #00AA00;">&#125;</span></pre></div></div>

<p>Пути к картинкам, конечно же, поставьте свои. Сами картинки можно взять: <a href="http://www.charnad.com/blog/wp-content/uploads/pictures/blockui/dialog-caption-bg.png">фон заголовка</a>, <a href="http://www.charnad.com/blog/wp-content/uploads/pictures/blockui/rotes_kreuz.png">крест</a>.</p>
<p>Теперь Javascript, чтобы все у нас прыгало и бегало.</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #006600; font-style: italic;">//По этим кнопкам модальное окно закрывается</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'.rotes_kreuz, .close_dialog'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        $.<span style="color: #660066;">unblockUI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066; font-weight: bold;">return</span> <span style="color: #003366; font-weight: bold;">false</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">//Эта кнопка будет вызывать наше окно</span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#show_modal'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        $.<span style="color: #660066;">blockUI</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span>message<span style="color: #339933;">:</span> $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#modal_dialog'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span> css<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span>width<span style="color: #339933;">:</span> <span style="color: #3366CC;">'275px'</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #006600; font-style: italic;">//По кнопке &quot;Да&quot; будет отправляться форма </span>
    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#modal_dialog #yes'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">click</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'#modal_dialog form'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">submit</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Можно скачать:[filebase:file:file=3:tpl=simple] или посмотреть прямо здесь.<br />
<input type="button" id="show_modal" value="Показать модальное окно">
<script type="text/javascript" src="http://www.charnad.com/files/blockui-modal-demo/jquery.blockUI.js"></script><script type="text/javascript">$.blockUI.defaults.css.border = '0px';$.blockUI.defaults.fadeIn = 100;$.blockUI.defaults.fadeOut = 100;$.blockUI.defaults.css.left = '40%';$(document).ready(function() {$('.rotes_kreuz, .close_dialog').click(function() {$.unblockUI();return false;});$('#show_modal').click(function() {$.blockUI({message: $('#modal_dialog'), css: {width: '275px'}});});$('#modal_dialog #yes').click(function() {alert('Да!');});});</script></p>
<style type="text/css">.dialog {cursor: default;border: 1px solid #000000;}.dialog form {margin: 0px;}.dialog .dialog_title_bar {height: 17px;padding: 1px;background-image: url(http://www.charnad.com/files/blockui-modal-demo/dialog-caption-bg.png) ;}.dialog .dialog_title_bar .dialog_caption {color: black;font-family: sans-serif;font-size: 9pt;text-align: left;padding-left: 5px;padding-top: 1px;}.dialog .dialog_pane {background: buttonface;text-align: center;padding-left: 10%;padding-right: 10%;padding-top: 10px;padding-bottom: 10px;}.dialog .dialog_button {width: 80px;height: 25px;}.dialog .rotes_kreuz {background-image: url(http://www.charnad.com/files/blockui-modal-demo/rotes_kreuz.png);width: 28px;height: 15px;position: absolute;right: 3px;top: 3px;float: right;display: block;cursor: pointer;}</style>
<div id="modal_dialog" style="display:none; cursor: default" class="dialog">
<div class="dialog_title_bar">
<div class="dialog_caption">www.charnad.com</div>
<div class="rotes_kreuz"></div>
</div>
<div class="dialog_pane">
<div>Наше модальное окошко</div>
<div style="margin-top: 10px;">
<form action="" method="POST">
<input type="button" id="yes" value="Да" class="dialog_button"/>
<input type="button" id="no" value="Нет" class="close_dialog dialog_button" /></form>
</div>
</div>
</div>
<p>При желании, вы легко можете добавлять поля в форму диалога. У этого плагина есть еще одна интересная черта - оповещения типа Growl (оповещение вверху справа), о котором я надеюсь написать в следующий раз.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/modalnoe-okno-na-jquery-blockui/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/modalnoe-okno-na-jquery-blockui/</feedburner:origLink></item>
		<item>
		<title>Пара советов по SQLite</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/2lrtmqP7ciE/</link>
		<comments>http://www.charnad.com/blog/para-sovetov-po-sqlite/#comments</comments>
		<pubDate>Fri, 29 Jan 2010 17:16:12 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[sqlite]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=926</guid>
		<description><![CDATA[Если у вас возникают ошибки при работе с SQLite, то вот у меня пара решений. Если у вас ошибка "Unable to open database file" и при этом база читается, даже если вы дали права файлу БД 0777, то вам еще надо дать права на запись папке, в которой лежит файл. Дело в том, что при [...]]]></description>
			<content:encoded><![CDATA[<p>Если у вас возникают ошибки при работе с SQLite, то вот у меня пара решений. </p>
<p>Если у вас ошибка "Unable to open database file" и при этом база читается, даже если вы дали права файлу БД 0777, то вам еще надо дать права на запись папке, в которой лежит файл. Дело в том, что при открытии транзакции пишется файл dbfilename-journal. Так же под Windows эта проблема может означать наличие кириллических символов в пути к базе.</p>
<p>Если вы по привычке написали ON DUPLICATE KEY UPDATE ..., и не понимаете в чем ошибка - обратитесь к <a href="http://www.sqlite.org/lang_insert.html">официальному мануалу</a> и просто измените INSERT на REPLACE, а "ON DUPLICATE..." сотрите.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/para-sovetov-po-sqlite/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/para-sovetov-po-sqlite/</feedburner:origLink></item>
		<item>
		<title>Ошибка PDO Invalid Argument и Unix socket</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/KfiSvkq9VtM/</link>
		<comments>http://www.charnad.com/blog/oshibka-pdo-invalid-argument-unix/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 14:56:32 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[pdo]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=910</guid>
		<description><![CDATA[Такая ошибка возникла у меня после перехода на PHP 5.3. Решение я нашел на http://stackoverflow.com, можете там посмотреть, чтобы узнать про эту ошибку более подробно. Выглядит она вот так: Warning: PDO::__construct&#40;&#41; &#91;pdo.--construct&#93;: &#91;2002&#93; Invalid argument &#40;trying to connect via unix://&#41; in /home/blah-blah-blah.php on line 9 &#160; Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[HY000] [2002] [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" style="float:left;" src="http://www.charnad.com/blog/wp-content/uploads/pictures/php.gif" alt=""/></p>
<p>Такая ошибка возникла у меня после перехода на PHP 5.3. Решение я нашел на http://stackoverflow.com, можете там посмотреть, чтобы узнать про эту ошибку более подробно. Выглядит она вот так:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">Warning: PDO::__construct<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #7a0874; font-weight: bold;">&#91;</span>pdo.--construct<span style="color: #7a0874; font-weight: bold;">&#93;</span>: <span style="color: #7a0874; font-weight: bold;">&#91;</span><span style="color: #000000;">2002</span><span style="color: #7a0874; font-weight: bold;">&#93;</span> Invalid argument <span style="color: #7a0874; font-weight: bold;">&#40;</span>trying to connect 
via unix:<span style="color: #000000; font-weight: bold;">//</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>blah-blah-blah.php on line <span style="color: #000000;">9</span>
&nbsp;
Fatal error: Uncaught exception <span style="color: #ff0000;">'PDOException'</span> with message <span style="color: #ff0000;">'SQLSTATE[HY000] [2002]
Invalid argument'</span> <span style="color: #000000; font-weight: bold;">in</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>blah-blah-blah.php:<span style="color: #000000;">9</span> Stack trace: <span style="color: #666666; font-style: italic;">#0</span>
<span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>blah-blah-blah.php<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #000000;">9</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>: PDO-<span style="color: #000000; font-weight: bold;">&gt;</span>__construct<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">'mysql:host=localhost;dbname=db'</span>, <span style="color: #ff0000;">'USER'</span>, 
<span style="color: #ff0000;">'PASSWORD'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #666666; font-style: italic;">#1 {main} thrown in /home/blah-blah-blah.php on line 9</span></pre></div></div>

<p>Решается она так: вместо localhost, при написании DSN для PDO пишите 127.0.0.1. А так же стоит указать путь к сокету MySQL в php.ini: pdo_mysql.default_socket=/var/run/mysqld/mysql.sock</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/oshibka-pdo-invalid-argument-unix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/oshibka-pdo-invalid-argument-unix/</feedburner:origLink></item>
		<item>
		<title>Гелиос-81Н</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/UvxqGcPfllA/</link>
		<comments>http://www.charnad.com/blog/gelios-81n/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 19:40:38 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[Прочее]]></category>
		<category><![CDATA[photo]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=891</guid>
		<description><![CDATA[Не так давно я купил себе зеркалку Nikon D60. Я достаточно долго щелкал на китовый объектив и, естественно, захотел новых игрушек. Китовый объектив я отдал хозяину, а себе купил кит от D90 Nikkor 18-105mm f/3,5-5.6, а чуть позже Гелиос-81Н 50мм f/2. Сейчас я коротенько расскажу про Гелиос. Все получилось относительно быстро. Я нашел статью в [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" title="Helios-81N" src="http://www.charnad.com/blog/wp-content/uploads/pictures/helios81n.png" alt="Helios 81N" />
<p>Не так давно я купил себе зеркалку Nikon D60. Я достаточно долго щелкал на китовый объектив и, естественно, захотел новых игрушек. Китовый объектив я отдал хозяину, а себе купил кит от D90 Nikkor 18-105mm f/3,5-5.6, а чуть позже Гелиос-81Н 50мм f/2. Сейчас я коротенько расскажу про Гелиос.</p>
<p><span id="more-891"></span>
<p>Все получилось относительно быстро. Я нашел статью в интернете про то, что советская оптика от фотоаппаратов Киев 17,19,20 имеет байонет Н. А тот в свою очередь был скопирован с никоновского байонета, и поэтому они совместимы без переходников. Это же просто находка для никониста! Из всех объективов с таким байонетом наиболее доступным, и наиболее мне интересным был как раз 81й.
<a href="http://www.charnad.com/blog/wp-content/gallery/helios-81n/img_71172-vk.jpg" title="" class="shutterset_singlepic60" >
	<img class="ngg-singlepic ngg-right" src="http://www.charnad.com/blog/wp-content/gallery/cache/60__160x120_img_71172-vk.jpg" alt="img_71172-vk" title="img_71172-vk" />
</a>
Мой экземплярчик я нашел на Ebay. Продавец оказался из Ростова, и за несколько дней мы договорились, что за ~23$ я получаю его себе. Теперь мой фотоаппаратик выглядит вот так:</p>
<p>Немножко инфы про объектив. Выпускается в нескольких вариантах, если вы хотите поставить его на камеру Nikon - ищите с маркировкой Н. 81 просто и 81-Автомат не подойдут. Почти полным аналогом является Арсат-81Н, разница в чернении лепестков диафрагмы и просветлении. По слухам на Арсатах чернение лепестков осыпается - будьте внимательны. Объектив, естественно, полностью ручной. Диафрагма выставляется в пределах от 2 до 22 на объективе, наведение на резкость производится фокусировочным кольцом. Выдержку и ISO выставлять надо в камере в режиме M. Насколько мне известно, автоматически оценивать экспозицию сможет только D200, но если у вас есть деньги на D200 - наверняка, есть деньги и на современный объектив. Угол поля зрения 45°, разрешение (центр/край) - 40/20 лин/мм. Опять же по памяти этот объектив один из самых лучших по разрешающей способности.</p>
<p>Поначалу, конечно, тяжко все выставлять ручками, привык, понимаешь, к автоматике. Но теперь получаю несравнимое удовольствие от управления всем процессом. Ну и, конечно куда без фоточек. Пока их мало, но я буду выкладывать по мере появления более-менее достойных. Моя первая модель - киска по имени Ириска.<br />

<a href="http://www.charnad.com/blog/wp-content/gallery/helios-81n/dsc_3579.jpg" title="" class="shutterset_singlepic59" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/59__140x105_dsc_3579.jpg" alt="dsc_3579" title="dsc_3579" />
</a>
 
<a href="http://www.charnad.com/blog/wp-content/gallery/helios-81n/dsc_3581_2.jpg" title="" class="shutterset_singlepic61" >
	<img class="ngg-singlepic ngg-left" src="http://www.charnad.com/blog/wp-content/gallery/cache/61__140x105_dsc_3581_2.jpg" alt="dsc_3581_2" title="dsc_3581_2" />
</a>
 
<a href="http://www.charnad.com/blog/wp-content/gallery/helios-81n/dsc_3597_2.jpg" title="" class="shutterset_singlepic62" >
	<img class="ngg-singlepic" src="http://www.charnad.com/blog/wp-content/gallery/cache/62__140x105_dsc_3597_2.jpg" alt="dsc_3597_2" title="dsc_3597_2" />
</a>
</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/gelios-81n/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/gelios-81n/</feedburner:origLink></item>
		<item>
		<title>PHP: Получить строку по номеру</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/AY9OBA1gKzM/</link>
		<comments>http://www.charnad.com/blog/php-poluchit-stroku-po-nomeru/#comments</comments>
		<pubDate>Mon, 11 Jan 2010 13:59:25 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[snippet]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=884</guid>
		<description><![CDATA[Мне нужно было получать строку из файла по порядковому номеру. То есть первую, десятую, 390815-ую, и т.д. Сначала мне хватало цикла fgets, который прокручивал до нужной строки. На строке 500000 такой способ у меня занимал уже почти минуту, что явно плохо. Stream_get_line был совем не быстрее, а даже медленнее процентов на 30. Первый из костылей, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" title="PHP" src="http://static.php.net/www.php.net/images/php.gif" alt="" width="120" height="67" />
<p>Мне нужно было получать строку из файла по порядковому номеру. То есть первую, десятую, 390815-ую, и т.д. Сначала мне хватало цикла fgets, который прокручивал до нужной строки. На строке 500000 такой способ у меня занимал уже почти минуту, что явно плохо. Stream_get_line был совем не быстрее, а даже медленнее процентов на 30.</p>
<p>Первый из костылей, пришедших мне в голову был fseek до значения в 500000 строк (посчитал байты), а оттуда уже крутил fgets. Но так как у меня идет обработка до 100 тысяч строк в сутки, то через пару дней опять пришлось высчитывать смещение для fseek. Опять же, требовался другой выход. И я его таки нашел.</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">function</span> getFileLine<span style="color: #009900;">&#40;</span><span style="color: #000088;">$file</span><span style="color: #339933;">,</span> <span style="color: #000088;">$line</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #990000;">trim</span><span style="color: #009900;">&#40;</span><span style="color: #990000;">exec</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;head -n <span style="color: #006699; font-weight: bold;">$line</span> <span style="color: #006699; font-weight: bold;">$file</span> | tail -n 1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Head берет N первых строк файла, tail N последних. Все гениальное просто. 1 миллионная строка берется из файла за 1.027 сек, 40 миллионная - 30 секунд, что очевидно быстрее прокручивания fgets.  (Конечно, если не прыгать fseek до 40 миллионной записи и считывать 40000001-ую)</p>
<p>Конечно, решение ограничено *nix системами, но т.к. моя система и без того использует pcntl_fork, она уже была привязана к никсам, так что хуже мне не стало.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/php-poluchit-stroku-po-nomeru/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/php-poluchit-stroku-po-nomeru/</feedburner:origLink></item>
		<item>
		<title>Массовый UPDATE в MySQL</title>
		<link>http://feedproxy.google.com/~r/charnad/~3/e85AowoCDek/</link>
		<comments>http://www.charnad.com/blog/massovyj-update-v-mysql/#comments</comments>
		<pubDate>Mon, 30 Nov 2009 21:22:18 +0000</pubDate>
		<dc:creator>CharnaD</dc:creator>
				<category><![CDATA[SQL]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://www.charnad.com/?p=841</guid>
		<description><![CDATA[Если вы хотите делать массовый апдейт в MySQL, то я могу вам предложить вот такой рецепт. Сначала вы создаете временную таблицу, циклом собираете массовый INSERT запрос и потом вставляете данные из временной таблицы в нужную. Выглядеть это может, например, так: CREATE TEMPORARY TABLE ids &#40;VALUE INT, url VARCHAR&#40;255&#41;&#41;; INSERT INTO ids VALUES &#40;0, 'http://url1.ru'&#41;, &#40;0, [...]]]></description>
			<content:encoded><![CDATA[<p><img class="oppic" src="http://www.charnad.com/blog/wp-content/uploads/pictures/mysql_logo.png" alt=""/>
<p>Если вы хотите делать массовый апдейт в MySQL, то я могу вам предложить вот такой рецепт. Сначала вы создаете временную таблицу, циклом собираете массовый INSERT запрос и потом вставляете данные из временной таблицы в нужную. Выглядеть это может, например, так:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TEMPORARY</span> <span style="color: #993333; font-weight: bold;">TABLE</span> ids <span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">VALUE</span> <span style="color: #993333; font-weight: bold;">INT</span><span style="color: #66cc66;">,</span> url <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">255</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> ids <span style="color: #993333; font-weight: bold;">VALUES</span> 
    <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'http://url1.ru'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'http://url2.ru'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
    <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'http://url3.ru'</span><span style="color: #66cc66;">&#41;</span>;
<span style="color: #993333; font-weight: bold;">UPDATE</span> blogs<span style="color: #66cc66;">,</span> ids <span style="color: #993333; font-weight: bold;">SET</span> my_value <span style="color: #66cc66;">=</span> ids<span style="color: #66cc66;">.</span><span style="color: #993333; font-weight: bold;">VALUE</span> <span style="color: #993333; font-weight: bold;">WHERE</span> blogs<span style="color: #66cc66;">.</span>url <span style="color: #66cc66;">=</span> ids<span style="color: #66cc66;">.</span>url;</pre></div></div>

<p>Поясню. Допустим, мне понадобилось обновить некое значение в таблице в соответствии с URL. Скажем, статистику интернет-магазинов. Я создал временную таблицу из тех значений, по котороым будет вестись поиск, и значений, которые я буду вставлять в нужную мне таблицу. Дальше, идет INSERT сразу нескольких строк. Его очень просто собирать в цикле из массива. Например вот так:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000088;">$elements</span> <span style="color: #339933;">=</span> <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #b1b100;">foreach</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$aray</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$url</span> <span style="color: #339933;">=&gt;</span> <span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #000088;">$elements</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">'('</span><span style="color: #339933;">.</span><span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">escape</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">', '</span><span style="color: #339933;">.</span><span style="color: #000088;">$db</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">escape</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$url</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">.</span><span style="color: #0000ff;">')'</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #000088;">$insert_string</span> <span style="color: #339933;">=</span> <span style="color: #990000;">implode</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">','</span><span style="color: #339933;">,</span> <span style="color: #000088;">$elements</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>После чего, собственно апдейт со вставкой. Временная таблица исчезнет после окончания сессии БД. На то она и временная.</p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.charnad.com/blog/massovyj-update-v-mysql/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		<feedburner:origLink>http://www.charnad.com/blog/massovyj-update-v-mysql/</feedburner:origLink></item>
	</channel>
</rss>

