-
Notifications
You must be signed in to change notification settings - Fork 0
Win32 powder coding tutorial
Hello, in this tutorial you will see how to program elements in Powder Toy, and get the basic knowledge about game’s mechanic.
The first thing you should know, that each element have it’s own number. Definitions of that numbers are on line 514:
#define PT_NONE 0
#define PT_DUST 1
...
#define PT_ETRD 50
#define PT_NICE 51
#define PT_NUM 52
Notice that each element has an incrementing ID and the last “element” is equal to number or elements, so when we would like to add one, we should put it behind PT_NUM and increase it’s number on 1.
#define PT_CHLR 52
#define PT_NUM 53
For example we will add PT_CHLR element. Next we should specify it’s physical properties and we can do this on line 574:
{"", 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, SC_OTHER, R_TEMP+0.0f, 251, "Erases particles."},
{"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, SC_OTHER, R_TEMP+0.0f, 70, "Very light dust. Flammable."},
.....
{"ETRD", PIXPACK(0x404040), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, 0.000f * CFDS, 0, 0, 0, 1, 1, 1, SC_ELEC, R_TEMP+0.0f, 251, "Electrode. Creates a surface that allows Plasma arcs. (Use sparingly)"},
{"NICE", PIXPACK(0xC0E0FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0005f* CFDS, 0, 0, 0, 0, 20, 1, SC_OTHER, -250.0f, 46, "Nitrogen Ice."},
These are the primary definitions for the elements.
Lets analyze the code here for the elements:
//Name Colour Advec Airdrag Airloss Loss Collid Grav Diffus Hotair Fal Burn Exp Mel Hrd M Section H Ins(real world, by triclops200) Description
NAME: what appears on the element Icon, always use four letters.
Colour: color in hexadecimal code
Advec, the closer the number to 1.0f the easier the particles separate.
AirDrag : how much the air slows it down
Airloss: how much air it generates in the direction of travel
Loss: how much velocity it looses, 1 = no loss .5 equals half loss
Collid: ?
Grav: how fast it falls, negative numbers means it floats
Diffus: how much the particles wiggle around
Hotair: how much it heats the environment around it
Fal: 1 or 0, does it move?
Burn: does it burn, 0 = no, higher numbers = amount
Exp: does it explode, the higher it is, the higher the pressure, up to 2.
Mel: does it melt, 1 for yes 0 for no
Hrd: how much acid affects it, the higher the more it is eaten
M: does it show up on the menu
Section: the section of the menu it is in
H: what heat does it start at? R_TEMP means spawning particle temp
Ins: specific heat value, can be found by using the real life heat value in J/G K (or KJ/KG K) by 96.635/RealLifeValue
Description: what shows when you mouse over the element.
Now lets add CHLR element:
{"NICE", PIXPACK(0xC0E0FF), 0.0f, 0.00f * CFDS, 0.90f, 0.00f, 0.0f, 0.0f, 0.00f, -0.0005f* CFDS, 0, 0, 0, 0, 20, 1, SC_OTHER, -250.0f, 46, "Nitrogen Ice."},
{"CHLR", PIXPACK(0xC2E76A), 1.0f, 0.01f * CFDS, 0.99f, 0.30f, -0.1f, 0.0f, 0.75f, 0.001f * CFDS, 0, 0, 0, 0, 0, 1, SC_GAS, R_TEMP+2.0f, 202, "Chlorine. Gas. Turns into the acid on contact with water."},
};
Now lets go to the table which controls states of matter of the elements.
Line 638:
// Name State Solid Frzp Liquid Mpnt Gas Bpoint Flametype Igpoint
/* NONE */ {ST_NONE, PT_NONE, 0.0f, PT_NONE, 0.0f, PT_NONE, 0.0f, PT_NONE, 0.0f},
State: what state of matter is it ST_SOLID, ST_LIQUID, ST_GAS, ST_NONE (for other)
Solid: what does it freeze into (ELEMENT ID such as PT_ICE goes here) PT_NONE for doesn’t freeze
Frzp: temperature at which it freezes
Liquid: what does it condense into?
Mpnt: condensation point.
Gas: what it boils into
Bpoint: the boiling point.
Flame type: what it burns into
Igpoint: what temp it burns at.
Lets add CHLR. It’s state is gas, and it don’t change it.
...
/* NICE */ {ST_SOLID, PT_NONE, 0.0f, PT_LNTG, -209.0f, PT_NONE, 0.0f, PT_NONE, 0.0f},
/* CHLR */ {ST_GAS, PT_NONE, 0.0f, PT_NONE, 0.0f, PT_NONE, 0.0f, PT_NONE, 0.0f},
};
The next bit is self explanatory
Line 696:
/* A B */
/* A 0 1 | B ligher than A */
/* B 1 0 | A heavier than B */
/* N D W O F M L G N C G P D I W S S W N P P A V W C D S S D B B P U W M P N L F B W R L H S G C B T P E N H */
/* o u a i i e a u i l a l f c i p n o e l l c o t n s a l m m r h r a W S S N o H H b R S a l s G h l t i T */
/* n s t l r t v n t n s e r e r r o o u u n i i r c t l t n t m o a x a c c 2 a o o d b C n a c l d s r c P * /
/* e t r l e l a p r e s x m i e k w d t t t d d v t w t w d l t t n x n n m l l m d N d s n a r m d e T */
/* NONE */ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
/* DUST */ {0,0,1,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
/* WATR */ {0,0,0,1,1,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
/* OILL */ {0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
Just add a new row and column for each element.
Now programming the element,
goto line 1964:
if(x+nx>=0 && y+ny>0 && x+nx<XRES && y+ny<YRES && pmap[y+ny][x+nx] && (pmap[y+ny][x+nx]&0xFF)!=PT_CLNE && (pmap[y+ny][x+nx]&0xFF)!=0xFF)
parts[i].ctype = pmap[y+ny][x+nx]&0xFF;
} else
create_part(-1, x+rand()%3-1, y+rand()%3-1, parts[i].ctype);
}
After the last bracket in this code add:
if (t==PT_CHLR)
{
}
This code will work only if the current part (t) is PT_CHLR.
Then add:
for(nx=-1; nx<2; nx++)
for(ny=-1; ny<2; ny++)
r = pmap[y+ny][x+nx];
if(x+nx>=0 && y+ny>0 && x+nx<XRES && y+ny<YRES && (nx || ny))
{
}
It is a “locator” which looks around the particle and puts current particle code into “r” variable. “r>>8” – part’s number in “parts” array and “r&0xFF” – is part’s type.
Here we check up is particle a kind of water, and is it alive (by looking into the center):
if(((r&0xFF)==PT_WATR||(r&0xFF)==PT_DSTW||(r&0xFF)==PT_WTRV||(r&0xFF)==PT_SLTW) && parts[pmap[y][x]>>8].type==PT_CHLR)
{
}
If true, we change current particle into acid, and delete CHLR:
parts[r>>8].type = PT_ACID;
parts[r>>8].life = 75;
delete_part(x,y);
Which “life” you should set you can see in the spawning code (near line 948). “Delete_part” function deletes part as you can see.
Now we check up if particle was salt water, and spawn salt for it:
if ((r&0xFF)==PT_SLTW)
create_part(-1,x,y,PT_SALT);
“create_part(p, x, y, t)” function spawns a particle with the type “t” at the place [x,y].
Full code:
if(t==PT_CHLR)
{
for(nx=-1; nx<2; nx++)
for(ny=-1; ny<2; ny++)
if(x+nx>=0 && y+ny>0 && x+nx<XRES && y+ny<YRES && (nx || ny))
{
r = pmap[y+ny][x+nx];
if(((r&0xFF)==PT_WATR||(r&0xFF)==PT_DSTW||(r&0xFF)==PT_WTRV||(r&0xFF)==PT_SLTW) && parts[pmap[y][x]>>8].type==PT_CHLR)
{
parts[r>>8].type = PT_ACID;
parts[r>>8].life = 75;
delete_part(x,y);
if ((r&0xFF)==PT_SLTW)
create_part(-1,x,y,PT_SALT);
}
}
}
This is all, hope this tutorial was helpfull.
Welcome to coding the powder toy!
This tutorial was based on Triclops200’s tut A big credit to him!