<?xml version="1.0" encoding="ISO-8859-1"?>
<rss version="2.0">
    <channel>
        <title>Programming Articles</title>
        <link>http://www.byond.com/members/ProgrammingArticles</link>
        <description>A place to learn more about the DM language.</description>
        <lastBuildDate>Fri, 18 Jul 2008 11:37:10 GMT</lastBuildDate>
        <language>en-us</language>
    
                <item>
            <title>Using Models</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=24648</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=24648</guid>
            <pubDate>Sat, 23 Dec 2006 12:21:33 GMT</pubDate>
            
            <comments>http://www.byond.com/members/ProgrammingArticles?command=view_comments&amp;post=24648#comments</comments>
            
            <description>A model is something that we use in order to predict/understand how a complicated system works - it describes how a system behaves. Models are usually not perfect and can be refined. An example of a model would be flipping a coin. One model might suggest that you have a 50% chance of getting heads on any given toss of the coin. But we can refine this model by adding to it that one side of the coin is heavier than other. This means that our model will now suggest you have a higher chance of getting one side than the other. But even then our model wouldn’t be perfect but it would still help us predict how the coin would land.&lt;br/&gt;
&lt;br/&gt;
Models can also be used in programming, but the beauty is that the model you create will actually give the exact desired effect in your world. If you say that the probability of getting heads on a coin is 50%, then the probability of getting heads WILL be 50% (assuming your calculations and programming is correct). If you want to use something realistic though, you’ll have to come up with some models for your world.&lt;br/&gt;
&lt;br/&gt;
Let’s suppose that there’re two people in a fight. Person A has a sword and is swinging it at person B who is stationary. Sir Isaac Newton’s second law of motion states that Force (F) = mass (m) * acceleration (a). If we let the sword be 4kg, person B be 3kg and say that as the sword hits person B, it is accelerating at 6 m/s^2 (6 metres per second squared), then we can work out the force that the sword strikes person B with.&lt;br/&gt;
&lt;br/&gt;
F = ma&lt;br/&gt;
F = 4 * 6 = 24N&lt;br/&gt;
&lt;br/&gt;
We could then say that person B is being pushed 24N. But the question is; what direction? If the sword were completely horizontal, then the 24N would be pushing person B completely horizontally. This usually isn’t the case though – the sword will most likely be a bit tilted. Let’s say that when the distance between person A and person B is 1 tile (that is to say they’re standing on tiles next to each other), then the sword always strikes person B at 30 degrees (to the horizontal). Let’s illustrate this on a diagram to make it clearer:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://members.byond.com/ProgrammingArticles/files/a4_1.PNG&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://members.byond.com/ProgrammingArticles/files/a4_2.PNG&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
From the diagram, we can see the force, the angle and the person are related in a triangle. &lt;br/&gt;
 &lt;br/&gt;
Every sloped line can be resolved (broken up into) a horizontal and vertical part. Which means that our sloped 24N can also be resolved horizontally and vertically. The horizontal part shows what horizontal force would be applied to B and the vertical part shows what vertical force would be applied to B. Together, they would move B in the north east direction (which is what the 24N represents). &lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://members.byond.com/ProgrammingArticles/files/a4_3.PNG&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The diagram shows the 24N can be resolved horizontally and vertically. You should know from basic trigonometry that cos x = adjacent/hypotenuse and that sin x = opposite/hypotenuse (adjacent being the side next to the angle, opposite being the side opposite the angle and hypotenuse being the largest side of a right angled triangle).&lt;br/&gt;
&lt;br/&gt;
Then we can work out the horizontal component of our 24N force:&lt;br/&gt;
&lt;br/&gt;
cos(30) = Horizontal/24&lt;br/&gt;
Horizontal = 24cos(30) = 20.78…N&lt;br/&gt;
&lt;br/&gt;
(The vertical force would then be 24sin(30). You can check these components are correct by using the Pythagorean theorem – (24cos(30))^2 + (24sin(30))^2 = 576, square root of 576 = 24N).&lt;br/&gt;
&lt;br/&gt;
Therefore we can say that a force of 24cos(30)N is acting horizontally on B when it’s struck by the sword. Let’s assume this is the only force acting on B, we don't want B to move vertically so we disregard 24N's vertical component.&lt;br/&gt;
&lt;br/&gt;
F = ma&lt;br/&gt;
24cos(30)N = 3kg * a&lt;br/&gt;
a = 24cos(30)/3 = 8cos(30) m/s^2&lt;br/&gt;
&lt;br/&gt;
This shows that person B will accelerate at 8cos(30)m/s^2 horizontally.&lt;br/&gt;
&lt;br/&gt;
Let's translate this into DM.&lt;br/&gt;
&lt;br/&gt;
&lt;DIV CLASS=&quot;dmcode&quot;&gt;&lt;TABLE WIDTH=100% BORDER=0&gt;&lt;TR&gt;&lt;TD&gt;&lt;PRE class=&quot;dmcode&quot;&gt;atom/movable/&lt;span class=dmkeyword&gt;var&lt;/span&gt;
    mass = 0
    acceleration = 0

obj/Sword
    mass = 4
    &lt;span class=dmkeyword&gt;verb&lt;/span&gt;/Strike(mob/M &lt;span class=dmkeyword&gt;as&lt;/span&gt; mob &lt;span class=dmkeyword&gt;in&lt;/span&gt; oview(1))
        acceleration = 6
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/force = mass * acceleration &lt;span class=dmcomment&gt;//24N&lt;/span&gt;
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/angle = 30
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/horizontal = force * cos(angle) &lt;span class=dmcomment&gt;//24cos(30)&lt;/span&gt;
        M.acceleration = horizontal/M.mass &lt;span class=dmcomment&gt;//24cos(30)/3 = 8cos(30)&lt;/span&gt;&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;br/&gt;
&lt;br/&gt;
At this point, we've worked out how fast person B will be accelerating (the reason lots of variables were used was because you might want to adjust the model).&lt;br/&gt;
&lt;br/&gt;
Using this value is up to you. One way of using it would be to say, let the person accelerate for 3 seconds and then say that the person is able to stop the force acting on him completely (which means that no more movement occurs after 3 seconds - the person is stationary). The person's displacement can be given by:&lt;br/&gt;
&lt;br/&gt;
&lt;a href=&quot;http://en.wikipedia.org/wiki/Equation_of_motion#Motion_equation_3&quot;&gt;s = ut + 1/2at^2&lt;/a&gt;&lt;br/&gt;
&lt;br/&gt;
s = displacement.&lt;br/&gt;
u = initial velocity.&lt;br/&gt;
a = acceleration.&lt;br/&gt;
t = time.&lt;br/&gt;
&lt;br/&gt;
We said the person is stationary at the top, which means that u = 0. Then:&lt;br/&gt;
&lt;br/&gt;
s = ut + 1/2at^2&lt;br/&gt;
s = 0*t + 1/2at^2&lt;br/&gt;
s = 1/2at^2&lt;br/&gt;
s = 1/2*a*3^2&lt;br/&gt;
s = 1/2*a*9&lt;br/&gt;
s = 4.5a&lt;br/&gt;
s = 4.5 * 8cos(30)&lt;br/&gt;
s = 36cos(30)&lt;br/&gt;
&lt;br/&gt;
The person moves approximately 31.1m horizontally. Translating this to DM gives:&lt;br/&gt;
&lt;br/&gt;
&lt;DIV CLASS=&quot;dmcode&quot;&gt;&lt;TABLE WIDTH=100% BORDER=0&gt;&lt;TR&gt;&lt;TD&gt;&lt;PRE class=&quot;dmcode&quot;&gt;atom/movable/&lt;span class=dmkeyword&gt;var&lt;/span&gt;
    mass = 0
    acceleration = 0
    u = 0 &lt;span class=dmcomment&gt;//initial velocity&lt;/span&gt;
    

obj/Sword
    mass = 4
    &lt;span class=dmkeyword&gt;verb&lt;/span&gt;/Strike(mob/M &lt;span class=dmkeyword&gt;as&lt;/span&gt; mob &lt;span class=dmkeyword&gt;in&lt;/span&gt; oview(1))
        acceleration = 6
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/force = mass * acceleration
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/angle = 30
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/horizontal = force * cos(angle)
        M.acceleration = horizontal/M.mass &lt;span class=dmcomment&gt;//24cos(30)/3 = 8cos(30)&lt;/span&gt;
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/time = 3 &lt;span class=dmcomment&gt;//as defined in the model&lt;/span&gt;
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/s = (M.u*t)+(0.5*M.acceleration*(3**2)) &lt;span class=dmcomment&gt;//the brackets are unnecessary but demonstrate what's happening - s = 36cos(30)&lt;/span&gt;&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;br/&gt;
&lt;br/&gt;
Now clearly moving the person 31 tiles in our world would seem stupid. Let's say each metre is 2 pixels.&lt;br/&gt;
&lt;br/&gt;
&lt;DIV CLASS=&quot;dmcode&quot;&gt;&lt;TABLE WIDTH=100% BORDER=0&gt;&lt;TR&gt;&lt;TD&gt;&lt;PRE class=&quot;dmcode&quot;&gt;atom/movable/&lt;span class=dmkeyword&gt;var&lt;/span&gt;
    mass = 0
    acceleration = 0
    u = 0 &lt;span class=dmcomment&gt;//initial velocity&lt;/span&gt;
    

obj/Sword
    mass = 4
    &lt;span class=dmkeyword&gt;verb&lt;/span&gt;/Strike(mob/M &lt;span class=dmkeyword&gt;as&lt;/span&gt; mob &lt;span class=dmkeyword&gt;in&lt;/span&gt; oview(1))
        acceleration = 6
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/force = mass * acceleration
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/angle = 30
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/horizontal = force * cos(angle)
        M.acceleration = horizontal/M.mass 
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/time = 3 
        &lt;span class=dmkeyword&gt;var&lt;/span&gt;/s = (M.u*t)+(0.5*M.acceleration*(3**2))
        s = round(s,1)
        &lt;span class=dmkeyword&gt;while&lt;/span&gt;(s&amp;gt;0)
            M.pixel_x += 2
            s--
            sleep(2)&lt;/PRE&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/DIV&gt;&lt;br/&gt;
&lt;br/&gt;
That would give the graphical effect of moving M s*2 pixels. Clearly there's a problem that pixel_x can only range from -127 to 127, but there are ways around that which you will have to implement yourself.&lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;Problems with the model.&lt;/b&gt;&lt;br/&gt;
&lt;br/&gt;
1) Everything has been treated as a particle. If a person is pushed with a force of 24cos(30), the person wouldn't really move a distance of 36cos(30) for several reasons. One reason is that your mass isn't concentrated all into one spot. It is easier for one to push your hand backwards than to push your entire body backwards. But in our model, we treat the person as a particle with its mass concentrated in a single point. The same goes for the sword.&lt;br/&gt;
&lt;br/&gt;
2) The model assumes that the sword always strikes the person at a 30 degree angle. This is clearly not the case and depends on the shape of person B and the sword. Accurate collision detection would allow you to draw a much better triangle and also work out the correct angle using some trigonometry.&lt;br/&gt;
&lt;br/&gt;
3) The model assumes that the force produced by the sword is the resultant force acting on person B. This clearly isn't the case in the real world. A gravitational field acts on your body and pulls you downwards to the centre of the Earth. A reaction force is produced by the surface your body is on which acts on you (Newton's 3rd law of motion). There might also be some air acting on you.&lt;br/&gt;
&lt;br/&gt;
4) The model assumes you always move for 3 seconds before stopping. This would however depend on many factors such as your strength.&lt;br/&gt;
&lt;br/&gt;
5) The model disregards friction when moving person B.&lt;br/&gt;
&lt;br/&gt;
6) The vertical force produced by the sword was completely ignored.&lt;br/&gt;
&lt;br/&gt;
There are probably even more flaws in the model that have not been explicitly pointed out.&lt;br/&gt;
&lt;br/&gt;
However, there is absolutely no need to make your game 100% realistic. You, the creator, can choose what you want in your world. And if your chosen model does not behave in the way you'd like it to, you can always refine it (not to make it realistic, but to make it how you wanted it to be in your head - your programming is just a model of what you want in your head).&lt;br/&gt;
&lt;br/&gt;
(Images are courtesy of Popisfizzy).</description>
        </item>
                <item>
            <title>Guild Started</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=14500</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=14500</guid>
            <pubDate>Thu, 29 Jun 2006 22:05:37 GMT</pubDate>
            
            <comments>http://www.byond.com/members/ProgrammingArticles?command=view_comments&amp;post=14500#comments</comments>
            
            <description>Everyone may join and support Programming Articles!</description>
        </item>
                <item>
            <title>Icon Scaling</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=4681</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=4681</guid>
            <pubDate>Wed, 19 Oct 2005 02:54:50 GMT</pubDate>
            
            <comments>http://www.byond.com/members/ProgrammingArticles?command=view_comments&amp;post=4681#comments</comments>
            
            <description>People often have to resort to programs such as Microsoft Paint or Photoshop when editing graphics. But who needs them when you’ve got DM on your side?&lt;br/&gt;
&lt;br/&gt;
First we’ll look at how to make an icon smaller.&lt;br/&gt;
&lt;br/&gt;
In order to get access to every pixel in the icon that we’re going to scale, we have to create a loop. To get every pixel, we would have to create two loops like so:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_1.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
This would mean going through the icon 1024 times, which would obviously be very slow. This is why instead of going through the icon at a pixel based level, we’ll go line by line. That’ll mean just creating one loop running 32 times.&lt;br/&gt;
&lt;br/&gt;
Lets assume we’ll be scaling an icon to half its original size. This’d mean that a pixel at (32,32) should appear at (16,16). And in the same way, a pixel at (1,1) should appear at (0.5,0.5). Unfortunately, we can’t get decimals in the icon since by definition, a pixel is an indivisible unit. So we’ll have to round all units. There’s a simple formula for where we want our pixels to appear – round(current_pixel_location * factor). We can test this formula; if the factor = 0.5: round(32 * 0.5) = 16 which is of course correct.&lt;br/&gt;
&lt;br/&gt;
 In order to get the pixel at one point to move to this location, we must use icon.Shift().&lt;br/&gt;
&lt;br/&gt;
At this point, the main problem is getting a line from the icon that we’re scaling. Wizkidd0123 has made a library called Pixel Functions which is able to isolate lines and single pixels too. The way it works is that you specify which icon you want to isolate something from, which exact line and whether it should be isolated vertically or horizontally.&lt;br/&gt;
&lt;br/&gt;
We’ll start by looping through the y co-ordinates. This’ll mean we have to isolate a line horizontally (think of a graph with the line y = 5 – the line would be horizontal). Next we figure out where this line should end up using our formula. Next we have to move the line there using Shift(). And finally we have to Blend() the displaced line into a final result. The problem is, we don’t know how much we want to Shift() and which direction. &lt;br/&gt;
&lt;br/&gt;
Since we’re taking horizontals, we have to Shift() these vertically. And since we’re scaling to make the icon smaller, we have to Shift() south. The amount by which me must Shift() is given by this formula: current_pixel_location – round(current_pixel_location * factor) . If we test this at factor 0.5 for the line at (32,32), we get: 32 – round(32*0.5) = 32 – 16 = 16. This makes sense because if we move a pixel at (32,32) down by 16 pixels, it’d appear at (32,16) which is where it should appear when the icon is halved. This pixel theory applies fully to lines as well.&lt;br/&gt;
&lt;br/&gt;
We get this:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_2.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The icon right now has only been scaled vertically, we have to scale it horizontally too to get a full effect. All this means is that we loop through the x co-ordinates and isolate vertical lines rather than horizontal. We can save each line into an icon and this icon would be the final result.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_3.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The key thing here is that we’re now scaling something that has been scaled once – we’re won’t be scaling the original icon.&lt;br/&gt;
&lt;br/&gt;
Ok this was easy enough, but what if we want to scale it and make the final result greater than before? i.e. Have a scale factor greater than 1.&lt;br/&gt;
&lt;br/&gt;
The first thing to realise is that we’ll have to go outside the regions of 32x32 icons. What we have to determine is how many icons are needed. If a 32x32 image is doubled, you get an image with the dimensions 64x64. If we look at this in terms of icons, you get 4. A tripled image would have the dimensions 96x96, which means 9 icons. A quadrupled image would have the dimensions 128x128, which means 16 icons.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_4.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
It becomes clear now that the total number of icons is the factor^2 (factor to the power of 2). But when the factor isn’t an integer, we get decimal answers. Rounding the answer is not safe because if the total number of icons is 5.4, it’d round to 5 which means there is still a 0.4 that hasn’t been taken care of. For this reason, we have to round every thing up. So even if the total number of icons is 5.01, we have to round this up to 6. A process to do this is commonly known as ceil() (ceiling).&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_45.png&quot;&lt;br/&gt;
&lt;br/&gt;
We now have to think of how we’re going to save these icons systematically. A good method is to save it in a 2D list - L[x][y]. What we can do is, say that first lets scale the icon across the screen. Add each of these scaled icons into L[x][1]. Then what we do is take the icons in L[x][1], and scale them up the screen. We can save them as L[x][y]. So effectively, you get a list of icons. That list has a list of icons going across the screen. Those lists have a list of icons directly above them.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_5.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_6.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
Please note that nothing will actually save at L[x], we’re saving at L[x][y].&lt;br/&gt;
&lt;br/&gt;
If we’re doubling the icon, we’ll have 4 icons in total. L[2][2]. 2 icons will be going across the screen. Those 2 get saved at L[1][1] and L[2][1]. Then the icon above L[1][1] gets saved at L[1][2]. The icon above L[2][1] gets saved at L[2][2].&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_7.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
We have to come up with a system that’ll create a list like that for us. The icons going across the screen is sqrt(number_of_icons) and going up the screen is again sqrt(number_of_icons). Therefore, our list of icons would be:&lt;br/&gt;
&lt;br/&gt;
var/list/ icons[sqrt(number_of_icons)][sqrt(number_of_icons)].&lt;br/&gt;
&lt;br/&gt;
Then we have to add Blank.dmi to each of element in the list.&lt;br/&gt;
&lt;br/&gt;
This is a nice way to do it:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_8.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The next job is to work out how many pixels wide the icon will be. This is easily achieved by doing sqrt(number_of_icons) * 32 which for integers will be factor * 32. Our loop this time will be go through py = 1 to total_pixels. When we’ve completed 32 lines, we have to tell the process to move on to the next icon across the screen. We first have to create a variable to track how many lines have been completed, lines_completed. To move on to the next icon across, we do L[current_across_location + 1][1]. This means we have to keep track of which across icon we’re on, we can call this current_image. We’ll also have to add a number variable to keep on increasing as the loop goes on, we can call this across_switcher. When ever we switch an icon, lines_completed will be restored too.&lt;br/&gt;
&lt;br/&gt;
Now we have to figure out which line to isolate and the Shift() value. We’ll call create a variable for the line that we’ll isolate, grabber. If we do 1/factor, we can start to figure out which line to isolate. To keep things simple, from now on we’ll assume that the factor is 2. 1/factor = 1/2 = 0.5. Each time a pixel is looped through, we can add 0.5 to grabber. We’ll obviously have to ceil() this value when ever we need want to isolate a line. 0.5 ceiled will be 1. So when px = 1, get line 1. When px = 2, add 0.5 to grabber. Therefore grabber will be 1. So when px = 2, get line 1. We also need to work out a Shift() value. We’ll make a table to see what happens:&lt;br/&gt;
&lt;br/&gt;
&lt;table&gt;&lt;table style=&quot;color:#FFFFFF&quot;&gt; &lt;table cellspacing='0' cellpadding='0' border='2'&lt;tr&gt;&lt;td&gt;Px&lt;/td&gt;&lt;td&gt;Grabber (ceiled grabber)&lt;/td&gt;&lt;td&gt;Shift&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.5 (1)&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;1.0 (1)&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;1.5 (2)&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;2.0 (2)&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;2.5 (3)&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;3.0 (3)&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br/&gt;
&lt;br/&gt;
What about scale factor 4?&lt;br/&gt;
&lt;br/&gt;
&lt;table&gt;&lt;table cellspacing='0' cellpadding='0' border='2'&gt;&lt;tr&gt;&lt;td&gt;Px&lt;/td&gt;&lt;td&gt;Grabber (ceiled grabber)&lt;/td&gt;&lt;td&gt;Shift&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;td&gt; &lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;0.25 (1)&lt;/td&gt;&lt;td&gt;0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2&lt;/td&gt;&lt;td&gt;0.50 (1)&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3&lt;/td&gt;&lt;td&gt;0.75 (1)&lt;/td&gt;&lt;td&gt;2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;4&lt;/td&gt;&lt;td&gt;1.00 (1)&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;5&lt;/td&gt;&lt;td&gt;1.25 (2)&lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;6&lt;/td&gt;&lt;td&gt;1.50 (2)&lt;/td&gt;&lt;td&gt;4&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;br/&gt;
&lt;br/&gt;
Our method of ceiling grabber is working out well. But we need a formula for the Shift() value. Look at the table, there is a pattern between Px, ceiled grabber and Shift. Shift = Px – ceil(grabber).&lt;br/&gt;
&lt;br/&gt;
Putting this all together, we get:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_9.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
Since our scale factor is 2, our list will look like:&lt;br/&gt;
&lt;br/&gt;
L[1][1] = Horizontally scaled icon&lt;br/&gt;
L[1][2] = Blank icon&lt;br/&gt;
L[2][1] = Horizontally scaled icon&lt;br/&gt;
L[2][2] = Blank icon.&lt;br/&gt;
&lt;br/&gt;
The next part is to scale the horizontally scaled icons vertically. First we create a loop, looping through all the icons across the screen. Next we have to scale each of these across icons vertically. Thankfully, this means running a similar loop as the horizontal one. But we have to change the condition for how current_image is switched.&lt;br/&gt;
In the image above, you’ll notice we created a variable called across that we never used. The use comes in now. First we do a while(across) loop, removing 1 each time that icon has been scaled. This means we get the bottom right icon and scale it up until the bottom left icon has been scaled up as well.&lt;br/&gt;
&lt;br/&gt;
The image being scaled will always be icons[across][1]. And now across_switcher will play the role of vertical_switcher, but we’ll keep on calling it across_switcher for simplicity’s sake.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_10.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
As for saving into the list, all we have to do is L[across][across_switcher], That’s literally all there is to change.&lt;br/&gt;
&lt;br/&gt;
As a final result, you should get this:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_11.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The method only works when the factor is greater than 1, so what we can do is to check whether the factor is greater than 1 or not. If it is, use the above method. Otherwise, use the method that we first started working with.&lt;br/&gt;
&lt;br/&gt;
Now you may wonder what you can possibly do with a list of strangely organized icons. The possibilities are endless but in order to unpack the list, you can do this:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a3_12.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
So then, who needs to go into Microsoft Paint and spend ages importing and exporting images into Dream Maker when you can scale icons using DM it self?</description>
        </item>
                <item>
            <title>Eliminating the Tile</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=4421</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=4421</guid>
            <pubDate>Fri, 07 Oct 2005 22:01:47 GMT</pubDate>
            
            <comments>http://www.byond.com/members/ProgrammingArticles?command=view_comments&amp;post=4421#comments</comments>
            
            <description>Many developers on BYOND complain about the 32x32 tile based movement system BYOND uses. There are however simple ways around it, but it means redesigning most of BYOND’s nice and friendly variables and processes.&lt;br/&gt;
&lt;br/&gt;
Firstly, it’s important to realise the variables that are concerned in this. There’re the locations variables; x, y, z and loc. You’ll have to make your own equivalent of all but the loc variable and z variable (the loc variable places you on the map and we shouldn't edit it. For the purposes of this article, and probably your game, we don't need to keep track of z). Next we’ll have to keep track of pixel_x and pixel_y into our own variable.&lt;br/&gt;
&lt;br/&gt;
Let’s call the location variables rx and ry (r meaning real). Let’s call the pixel offsets px and py (p meaning pixel).&lt;br/&gt;
&lt;br/&gt;
How are we going to start moving you ask? Using the client direction procs, such as client/North(). These are called when you hit a key on your keyboard. They then call client/Move(). client/Move() then calls client.mob.Move() which is essentially mob/Move(). First, let’s start moving pixel by pixel:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_1.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
That’s pretty much all there’s to eliminating the 32x32 movement system. But the problem is that we have to know what our co-ordinates are on the map each time we move a pixel. You can’t just keep on increasing the mob’s location by 1 since all we’ve done is move 1 pixel, not 1 tile. It isn’t as simple as saying, after pixel_y is 32, add 1 to the location. If you imagine a 32x32 object, it reaches half way through the next tile after only 16 pixel moves. So once it reaches over half way, it’s fair to say that’s more of it is on the other tile therefore we’re going to make its location the other tile too.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_2.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
We’re no longer going to use the default x and y location variables because setting them means that we actually move there too. This is undesirable because if your pixel_y is 17 and your y variable has increased by 1, it’d look like you moved 1 step rather than 1 pixel! So what we do is, we keep track of what our real location would be (so that we can refer to it if ever needed) and we completely abandon the x and y variables. So what we’re trying to do in client/North() is to increase our pixel offset by 1 and keep track of what our location should be. In order to do that, we also need to keep track of what our pixel_y variable is. We can’t simply use pixel_y to keep track of things for reasons that’ll become obvious soon.&lt;br/&gt;
&lt;br/&gt;
This is what you should get:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_3.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The next problem comes at the limitations of pixel_y. pixel_x and pixel_y are signed integers, which means that their value is limited. You can’t use pixel_y after 127. So what we’ll do is, move the mob to where it REALLY should be and thus restore pixel_y back down to 0. The y location may be greater than world.maxy, so in that case, we’ll restore it to world.maxy instead.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_4.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The next thing to take into consideration is collision detection. You would normally detect collision through the Bump() proc, but if we’re not moving tile by tile (and are therefore breaking BYOND’s default movement system) how are two things meant to collide? The answer is that we draw a border around each and every object. What a border means is that if that border is crossed, we can say collision has occurred. If you’re working with 32x32 icons, you’ll probably want to place this around the edges. But you can if you want, regardless of icon size, place it anywhere in the middle of the 32x32 icon. &lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_5.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The red object is moving into the yellow object. The yellow object’s blue border has been crossed. This means collision has occurred. It is vital that you understand this concept of crossing the border.&lt;br/&gt;
&lt;br/&gt;
How do we implement this into BYOND? First you’ve got to define the variables holding the border (no you don’t literally draw the border on the icons).  Four variables: bottom, top, left and right. If you want the bottom edge of a 32x32 icon to be the bottom border, make bottom equal 32. If you want the left edge of a 32x32 icon to be the left border, make left equal 32. You should have the following variables:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_6.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
The variables defined for collisions have the value of the outside edges of a 32x32 icon. There is a good reason for why we choose 32 for bottom + left and 0 for top and right – it’s for the calculations that will be needed to be done. If you wanted collision to occur at the middle of the icon, you’d define bottom as 16 and left as 16. If you wanted collision to occur 4 pixels above the bottom of the icon, define bottom as 28 (32-4). If you want this collision to stop 12 pixels below the top of the icon, define top as 12. Left and right work similarly too.&lt;br/&gt;
&lt;br/&gt;
Essentially, bottom is used to define where collision starts when using client/North() and top is used to define where it stops. left  is used to define where collision starts when using client/East() and right is used to define where it stops. This is reversed if we’re doing client/South() – top is used to define where it starts and bottom is used to define where it stops. Same for client/West().&lt;br/&gt;
&lt;br/&gt;
Let’s assume we’re currently fully on a 32x32 tile (so our pixel offsets haven’t been changed). If we move north, we’re saying that there’s a possibility of a collision directly above us (ry + 1). So we need to check if that turf is dense, if it is let’s end all possible movement (you can change this in your game). If it isn’t dense, we need to search it for a mob and an obj. If we find one, lets compare our pixel_y to where collision is supposed to occur in that atom/movable. For example, if collision occurs in that atom/movable right at the border (so bottom = 32), any value greater than 0 for py should work (if we’ve taken 1 pixel step, then we must have cross its border by 1 pixel and so we must have collided). &lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_7.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
You’ll now notice that this works fine if our pixel offset is 16 or below, but what about if our py is –16 (pixel_y = 17)? We have to handle it separately because we’ll now be using the top variable and the formula is different:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/a2_8.png&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
And there you have it, pixel movement with collision detection! To do this for client/East(), just change the y’s to x’s, bottoms to lefts and tops to rights. To do this for client/South(), just reverse everything done in client/North(). To do this for client/West(), just reverse everything done in client/East().&lt;br/&gt;
&lt;br/&gt;
In addition to collision detection, you’ll want to implement how and when Enter() is called, I suggest to do it when ever the icon of the mob is fully overlaying a tile or when you’re 16 pixels into the tile (pixel_y = 16).&lt;br/&gt;
&lt;br/&gt;
You may also want to increase how many pixels you move per step; 1 is very slow. It'll unfortunately mean more than just doing pixel_y += 2. &lt;br/&gt;
&lt;br/&gt;
Finally, please note this is just guidance towards eliminating the tile - it is not a bulletproof library to be implemented into your game. There are probably more than half a dozen problems you'll run into in an actual game if you use just what is posted here.</description>
        </item>
                <item>
            <title>Interaction</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=4289</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=4289</guid>
            <pubDate>Sat, 01 Oct 2005 14:56:52 GMT</pubDate>
            
            <comments>http://www.byond.com/members/ProgrammingArticles?command=view_comments&amp;post=4289#comments</comments>
            
            <description>Many of us have tried to interact between different types of atom and have mostly succeeded. But success doesn’t mean you did it right. &lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;&lt;u&gt;turf/Enter() &lt;/b&gt;&lt;/u&gt;&lt;br/&gt;
&lt;br/&gt;
Enter() is only called when something moves onto the turf. It is useful because one can decide whether or not to let the thing Enter()ing enter or not. It is no place to be doing any programming in which you’re going to do anything not related to simply allowing entry or not – such as teleportation to other locations or display messages to the thing Enter()ing. Enter() should only be used to decide whether or not to let the thing Enter()ing enter or not. To do this, you must return values. 1 if you want the thing to enter or 0 if you don’t want the thing to enter. One example showing this would be:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/eg1.png&quot; alt=&quot;Image hosted by Photobucket.com&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
Enter() can also be used to get past density checks. If you return 1 and if density exists, you would still Enter() the turf.&lt;br/&gt;
&lt;br/&gt;
In no case however must you assume that the thing Enter()ing will be a player, or even a mob for that matter. It is vital that you run checks before doing anything. Here’s an example showing what not to do:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/eg2.png&quot; alt=&quot;Image hosted by Photobucket.com&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
Ok sure this’ll run fine when you go and test it, but have you really thought of all possibilities? What happens if a non-client Enter()s? Or what if it’s an obj that is Enter()ing? You’re just assuming that there’s a usr there – and in programming, you don’t assume.&lt;br/&gt;
&lt;br/&gt;
First, we need a way to refer to the thing that is Enter()ing. You can do that easily by defining a variable in turf/Enter(). But you can’t just do turf/Enter(mob/M) because it could easily be an obj that’s Enter()ing. You would get a runtime error like runtime error: undefined variable /obj. We know only something that can Move() will be able to Enter() our turf, therefore we can say that atom/movable will always be safe. &lt;br/&gt;
&lt;br/&gt;
Next we must check to see whether or not the thing Enter()ing is a mob or an obj. A simple ismob() and isobj() test will figure that out. After running one, you should refer to the variable atom/movable/A as var/mob/M or var/obj/O if you plan on accessing mob/obj specific variables and/or procs.&lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;&lt;u&gt;turf/Entered() &lt;/b&gt;&lt;/u&gt;&lt;br/&gt;
&lt;br/&gt;
This is where you should do programming that happens after the thing has successfully Enter()ed - such as teleportation or displaying messages to the thing that Entered(). It is called only when Enter() returns 1. It won’t be called if Enter() returned 0.&lt;br/&gt;
&lt;br/&gt;
&lt;br/&gt;
Everything said for Enter() applies to Entered() so there’s no point in repeating what is already written above.&lt;br/&gt;
&lt;br/&gt;
A very useful function of Entered() is that we can know where the thing that Entered() is coming from. To do this, simply put a second argument for turf/Entered() and then you can refer to the old location. Uses include getting the distance between the two locations, checking if they came from the right place and sending them back to the old place too.&lt;br/&gt;
 &lt;br/&gt;
Ok so we’ve figured out how to get interaction between turfs and movable atoms, but what about interaction between just movable atoms?&lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;&lt;u&gt;Bump()&lt;/b&gt;&lt;/u&gt;&lt;br/&gt;
&lt;br/&gt;
This is one of the most misunderstood procs I’ve ever seen. The way it works is that the atom you define Bump() for will be the thing that has to move and collide with something to call Bump() and the thing you define within the Bump() will be the thing collided.&lt;br/&gt;
&lt;br/&gt;
For example:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/eg3.png&quot; alt=&quot;Image hosted by Photobucket.com&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
In this, considering something has caused obj/Knife to move, if the Knife collides with a mob or an obj that has density, Bump() for the Knife will be called.&lt;br/&gt;
&lt;br/&gt;
Again you must not assume that the thing you’re Bump()ing is a player/client/mob/obj, you need to know! Similar checks used in turf/Enter() will be necessary here. First define the thing that is getting collided. Next, check if it’s a mob or an obj and then define a variable for it accordingly.&lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;There is no place for usr in Bump()&lt;/b&gt;&lt;br/&gt;
&lt;br/&gt;
An example of a strong Bump() system:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/eg4.png&quot; alt=&quot;Image hosted by Photobucket.com&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
&lt;b&gt;&lt;u&gt;Bumped() &lt;/b&gt;&lt;/u&gt;&lt;br/&gt;
&lt;br/&gt;
In some cases, you may not want to Bump() something but rather have that thing be Bumped() instead. There is no Bumped() proc defined in the DM language, but it is simple enough to make your own. Here is an efficient one I’ve found on the forums:&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/Bumped.png&quot; alt=&quot;Image hosted by Photobucket.com&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
Bumped() works exactly like Bump() only instead of defining the thing Bump()ed, we define the thing that’s Bump()ing.&lt;br/&gt;
&lt;br/&gt;
If you do include Bumped() in your projects, be sure to realize that both Bump() and Bumped() won’t be called in a collision between two atoms.&lt;br/&gt;
&lt;br/&gt;
&lt;img src=&quot;http://img.photobucket.com/albums/v234/deathawaitsu/eg5.png&quot; alt=&quot;Image hosted by Photobucket.com&quot;&gt;&lt;br/&gt;
&lt;br/&gt;
In this case, all you’ll ever see is “The knife hit the victim”. You won’t ever see “Victim got hit by the knife” because Bump() takes precedence over Bumped().&lt;br/&gt;
&lt;br/&gt;
In conclusion of all interaction: Always have variables know what are the two things involved in the interaction. Run validity checks. Do relevant-to-the-game programming last. &lt;b&gt;Don’t use usr! &lt;/b&gt;</description>
        </item>
                <item>
            <title>Introduction</title>
            <link>http://www.byond.com/members/?command=view_post&amp;post=4288</link>
            <guid>http://www.byond.com/members/?command=view_post&amp;post=4288</guid>
            <pubDate>Sat, 01 Oct 2005 14:56:32 GMT</pubDate>
            
            <comments>http://www.byond.com/members/ProgrammingArticles?command=view_comments&amp;post=4288#comments</comments>
            
            <description>This is a place where people who have a decent understanding of DM can come and learn about programming. The service is clearly free and meant to be educational. &lt;br/&gt;
&lt;br/&gt;
All topics are up for debate and feel free to ask questions. &lt;br/&gt;
&lt;br/&gt;
Currently there is just 1 member in this team, hopefully this can change over time.&lt;br/&gt;
&lt;br/&gt;
We aim to publish articles regularly.</description>
        </item>
            
    </channel>
</rss>

