Coding-tutorial/ru
From The Powder Toy
Jump to: navigation, search
Эта страница актуальна с 1/29/11, ибо используется последний ghitub исходный код </h2>
Видео-туториал по ссылке - :
gamerboy8864 туториал о том как сделать мод для Powder Toy//
Туториал ориентирован и переведён чтобы дать русским знание о том как создавать в этой игре элементы. Мы будем создавать нагревательный элемент Триклопс200 тут. Цвет будет как у элемента HEAT, и он будет неразрушимым твердым вещевством в специальном меню, который быстро передает тепло. Свяжитесь с cracker64(если вы знаете английский) если имеете проблемы с созданием.
Создавать элементы не так легко как вписать цвет, имя и особенности, но примерно так и будет в действительности легко.
Заметка: включите нумерование линий. Это удобно, чтобы не искать в дебрях код.
Часть первая: установление умолчаний у элемента
Шаг первый: добавление ссылки на элемент
Откройте файл powder.h любым редактором на ваш выбор и перейдите на линию 199 (найдите: #define PT_NUM)
- define PT_NONE 0
- define PT_DUST 1
...
- define PT_FROG 145
- define PT_BRAN 146
- define PT_NUM 147
Каждый элемент в игре имеет свой ID, есть также скрытый элемент, точнее не совсем элемент который называется - PT_NONE он обозначает буквально пустоту, и его ID равен 0, то есть последнее чисто после типа элемента.
Добавим новое значение.
С каждым новым элементов ему придается ID больше, чем последний элемент до PT_NUM. PT_NUM это уже количество элементов в игре (PT_NONE начинается с нуля).
- define PT_BRAN 146
- define PT_HETR 147
- define PT_NUM 148
Поместите элемент перед PT_NUM, и обязательно добавьте к элементу приставку PT_. Дайте элементу ID тот же что и у PT_NUM, а у PT_NUM увеличьте на единицу, как на примере. Ни один элемент не должен иметь одинаковых ссылок, иначе ошибка, или хуже всего, добавление сразу двух элементов, но это невозможно.
Step Two: установка значений свойствам элемента(кто знает программирование Дельфи элемент это класс, однако в него нельзя добавить функции и процедуры напрямую, поскольку в С программирование классов отличается значительно)
Откройте powder.h и перейдите на линии 519 (найдите: {"BRAN", PIXPACK(0xCCCC00) )
{"", PIXPACK(0x000000), 0.0f, 0.00f * CFDS, 1.00f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, R_TEMP+0.0f +273.15f, 251, "Erases particles.", ST_NONE, 0, NULL},
{"DUST", PIXPACK(0xFFE0A0), 0.7f, 0.02f * CFDS, 0.96f, 0.80f, 0.0f, 0.1f, 0.00f, 0.000f * CFDS, 1, 10, 0, 0, 30, 1, 85, SC_POWDERS, R_TEMP+0.0f +273.15f, 70, "Very light dust. Flammable.", ST_SOLID, TYPE_PART, NULL},
.....
{"FROG", PIXPACK(0x00AA00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 100, SC_LIFE2, 9000.0f, 40, "Frogs S12/B34/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL},
{"BRAN", PIXPACK(0xCCCC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 100, SC_LIFE2, 9000.0f, 40, "Brian 6 S6/B246/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL},
//Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Weights Section H Ins Description State Properties Function
Это основные свойства(умолчания) элемента. Здесь вы видите различные значения и название свойств сверху.
Name: Имя элемента, всегда используйте значение из 4 букв, даже если элемент имеет 3.
Colour: Цвет в 16-чном значении. Воспользуйтесь любым графическим редактором чтобы узнать цвет и его значение в 16 исчислении. 16-чный код ВСЕГДА должен идти после префикса 0х.
Advec: Насколько ускоряется частица элемента под движением воздуха?
Airdrag: Сколько создается воздуха при движении частицы?
Airloss: Насколько сильно ослабляет воздух частица элемента? (То есть насколько имеет эффект стены). 1 = нет эффекта, 0 = максимальный эффект.
Loss: Сколько теряет скорости частица после каждого кадра(FPS). 1 = без потерь, .5 = теряется половина.
Collid: Как сильно умножается скорость после ударения с любым элементом(кроме PT_NONE конечно:) ).
Grav: Воздействие гравитации на частицу элемента. При отрицательном, будет плавать.
Diffus: Насколько сильно частица стремится заполнить пространство(как газ NBLE).
Hotair: Насколько увеличивается частица под давлением как ни странно.
Fal: Как двигается частица? 0 = твердое тело, 1 = порошок, 2 = жидкость
Burn: Может гореть? 0 = нет, чем больше цифра = сильнее "выжигание".
Exp: Взрывается? 0 = нет, чем больше цифра = тем выше создается давления.
Mel: Может расплавится? 1 = да, 0 = нет.
Hrd: Насколько частица имеет эффект кислоты? 0 = нет эффекта, чем выше номера = тем выше эффект.
M: Показывается в меню? 1 = да, 0 = нет.
Weight: Вес частицы. 1 = Газ. 2 = легкая, 98 = тяжелая (жидкости 0-49, порошки 50-99). 100 = твердая. -1 это нейтроны и фотоны.
Section: Секция в меню. Префикс должен быть 'SC_'.
H: Какую температуру имеет при создании? Температура в кельвинах (Кельвин = температура Цельсия + 273.15). R_TEMP+273.15f даст комнатную температуру(по умолчанию 22).
Ins: Особое значение (Насколько быстро частица передает тепло).0 - Тепло не передается(частица и не нагревается попросту), 250 - Максимально.
Description: Описание элемента в меню, когда наводишь мышь на него.
State: Какое состояние у элемента? Опции могут быть ST_NONE(никакое, как HEAT, VAC и.т.д.), ST_SOLID(Твердое), ST_LIQUID(Жидкое), ST_GAS(Газ).
Properties: Какие особые виды свойств имеет вещевство? Свойства найдете на линии ~214. разделяйте свойства знаком - |.
Function: Функции, обсуждаются во второй части.
Вот описание всех начальных свойств класса-элемента. Ниже приведен код который показывает что мы должны будем написать:
...
{"BRAN", PIXPACK(0xCCCC00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 0, 1, 100, SC_LIFE2, 9000.0f, 40, "Brian 6 S6/B246/3", ST_NONE, TYPE_SOLID|PROP_LIFE, NULL},
{"HETR", PIXPACK(0xFFBB00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, 22.0f+273.15f, 251, "Heats objects it touches", ST_SOLID, TYPE_SOLID, NULL},
};
Шаг три: установка параметров изменения состояния.
Открываем powder.h,на линии 681 (Найдите: /* GOL */ {IPL ... )
{ // if low pressure if high pressure if low temperature if high temperature
// Name plv plt phv pht tlv tlt thv tht
/* NONE */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
/* DUST */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
Это часть кода совершенно новая, в общем представляет из себя таблицу состояний, точнее условия для фазовых переходов. Например WATR, она замерзает при 273.15 Kельвинах, в таблице указано что при низкой температуре вода должна превратится в ICE. Или вода испраряется при 373 кельвинах. Это линия про WATR:
/* WATR */ {IPL, NT, IPH, NT, 273.15f,PT_ICEI, 373.0f, PT_WTRV},
Также таблица указывает на переходы от давлений, что дает ICE превращаться в SNOW, это указывается в таблице аналогично температуре, это изменение от низкого давления(ниже нуля) и высокого(выше нуля), вот линия для ICE:
/* ICE */ {IPL, NT, 0.8f, PT_SNOW, ITL, NT, 233.0f, ST},
В общем не буду вам парить мозг, тем что дальше написал автор оригинала, а расскажу про синтаксис, он таков:
В скобках /* Тут имя вещевства */ далее открываем фигурные скобки, и пишем вначале давление(оно низкого типа) необходимое для перехода в другое вещество (ВНИМАНИЕ! ЕСЛИ ЧИСЛО НЕ ЦЕЛОЕ, СТАВЬТЕ В КОНЦЕ БУКВУ f), далее через запятую пишем это вещевство, и ставим запятую, если без переходов пишем в первом IPL, во втором NT(NT будет везде где не нужно использовать переходы (!!!)), следующие три аналогичны по написанию я лишь приведу для чего они и их ну как это не знаю, в общем тоже самое что и IPL.
Вот список по порядку всех условий:
Какое давление ниже нуля(минус не ставьте)
Какое давление выше нуля
Какая температура ниже нуля(использовать кельвины)
Какая температура выше нуля(использовать кельвины аналогично)
А вот этого, что я не знаю как назвать:
IPL
IPH
ITL
ITH
Ниже показан код для Триклопса
...
/* GOL */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
/* HETR */ {IPL, NT, IPH, NT, ITL, NT, ITH, NT},
};
Step Four: Defining the Element's Special Properties
At this point, you would be able to compile, and the HETR would show up in the menu and you can place it, BUT it doesn't do anything! Now for the part where we actually code what the element does. Make sure to save powder.h.
This is also where new element creation is different from before, if you look inside the src folder, you will now see an elements folder. Inside here is a *.c file for each major element.
Now we need to make a hetr.c file for our new heater element, if using visual studio, you should be able to right click on the source folder inside the project, and create a new file, and name it hetr.c Once you have a blank hetr.c created and it is included in the project, we need to add a few things to this file.
- include <element.h>
int update_HETR(UPDATE_FUNC_ARGS) {
return 0;
}
Before we go on with the actual code, we need to finish up a few things first so that the code actually knows there is a new update_HETR function. Go back to powder.h at line ~250. You will see lots of int update_'(UPDATE_FUNC_ARGS); . This list is sorted alphabetically so lets put in our new HETR function.
int update_GOO(UPDATE_FUNC_ARGS);
int update_HETR(UPDATE_FUNC_ARGS);
int update_HSWC(UPDATE_FUNC_ARGS);
Remember that function variable in the ptypes array? we need to let it know that HETR has a special function to use, instead of NULL. Replace NULL with &update_HETR.
{"HETR", PIXPACK(0xFFBB00), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 0, 1, 1, 100, SC_SPECIAL, 22.0f+273.15f, 251, "Heats objects it touches", ST_SOLID, TYPE_SOLID, &update_HETR},
Now that our new HETR function will be called properly, we can go back into hetr.c and finish it up. NOTE: Put all code BEFORE the return 0; line so when it finishes running, it will go back to the main code. If you kill the particle from inside the function, please return 1;. Our HETR element will not die, so you don't have to worry about that.
Now we need to go over some useful ways of detecting particles, so that we can heat them.
for(rx=-1; rx<2; rx++)
for(ry=-1; ry<2; ry++)
This code simply means "any particle touching a heater particle".
It basically sets the grid size in which particles are affected by the effect of the particle. In this case, it is a 3x3 grid around the center one. If you are having trouble getting this, try thinking about rx and ry, as a radius around the current particle.
for(rx=-2; rx<3; rx++)
for(ry=-1; ry<2; ry++)
This would make the grid affected 5x3
for(rx=-1; rx<2; rx++)
for(ry=-2; ry<3; ry++)
And this would flip the dimensions.
Add this:
if(x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES &&
pmap[y+ry][x+rx] &&
(pmap[y+ry][x+rx]&0xFF)!=PT_HETR&&
(pmap[y+ry][x+rx]&0xFF)!=0xFF)
{
Your entire code should look like this so far:
for(rx=-1; rx<2; rx++)
for(ry=-1; ry<2; ry++)
1 if(x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES &&
2 pmap[y+ry][x+rx] &&
3 (pmap[y+ry][x+rx]&0xFF)!=PT_HETR&&
4 (pmap[y+ry][x+rx]&0xFF)!=0xFF)
5 {
1st line: If the current grid particle around the HETR pixel is within the screen, AND
2nd line: there is a particle in that point, AND
3rd line: that particle is not a HETR, AND (note: != means not equal)
4th line: that particle is not a wall,
5th line: THEN, do some code
Now add this:
r = pmap[y+ry][x+rx];
It means you can just type 'r' instead of 'pmap[y+ry][x+rx]'. This will simplify code later on.
NEW: because our hetr.c file is separate, we need to initialize these variables we are using inside hetr.c, add this as the first part of the update_HETR function.
int r, rx, ry;
Now add
if(parts[r>>8].temp + (parts[r>>8].temp*0.2f)<=MAX_TEMP)
Let's analyze.
1) if ()
IF a is true, THEN b happens
2) parts[r>>8]
The currently selected particle (the one that's not HETR or a wall)
3) .temp
means it's temperature.
In English, the statement reads:
IF the particle's temperature + 20% of it's temperature is less then then the maximum temperature possible, THEN...
This ensures it won't go over the maximum temperature. Now add this:
parts[r>>8].temp += parts[r>>8].temp*0.2f;
In English,
IF the particle's temperature + 20% of it's temperature is less then then the maximum temperature possible, THEN add 20% of the particle's temperature to itself.
Now add:
else {
parts[r>>8].temp = MAX_TEMP;
}
IF the particle's temperature + 20% of it's temperature is less then then the maximum temperature possible, THEN add 20% of the particle's temperature to itself, ELSE the temperature is the maximum temperature.
Now close the two brackets we used for the if statements to complete the section.
The entire hetr.c should now look like this:
- include <element.h>
int update_HETR(UPDATE_FUNC_ARGS) {
int r, rx, ry;
for(rx=-1; rx<2; rx++)
for(ry=-1; ry<2; ry++)
if(x+rx>=0 && y+ry>0 && x+rx<XRES && y+ry<YRES &&
pmap[y+ry][x+rx] &&
(pmap[y+ry][x+rx]&0xFF)!=PT_HETR&&
(pmap[y+ry][x+rx]&0xFF)!=0xFF)
{
r = pmap[y+ry][x+rx];
if(parts[r>>8].temp+ (parts[r>>8].temp*0.2f)<=MAX_TEMP)
{
parts[r>>8].temp += parts[r>>8].temp*0.2f;
}
else
{
parts[r>>8].temp = MAX_TEMP;
}
}
return 0;
}
Congrats, your HETR element should now work.
Part Two: Uploading Your Work to GitHub (NOTE: GitHub is NOT necessary to just add elements, it is for getting code into the official)
1) Open SmartGit (make sure you've saved your changes in Visual Studio).
2) powder.c and any other files you may have changed should be listed as "Modified".
3) Press "Commit" at the top, list the things you have changed in the text box, and press "Commit".
4) Press "Push" at the top, and press "Push" again.
5) Go to your Powder Toy repository page on GitHub and press "Pull Request" at the top.
6) Send the request to facialturd (Simon's username) and you should be done. Verify that the code has been changed if you like.
7) If Simon decides to accept your request, your code will be in the official Powder Toy source code. Congratulations!
Now you are done, if you have any more questions, type them at the discussion part of this page.
Welcome to coding the powder toy!
- define PT_NONE 0
- define PT_DUST 1
- define PT_FROG 145
- define PT_BRAN 146
- define PT_NUM 147
- define PT_BRAN 146
- define PT_HETR 147
- define PT_NUM 148
- include <element.h>
- include <element.h>