Omnimaga
Calculator Community => TI Calculators => Axe => Topic started by: yunhua98 on March 11, 2011, 04:18:08 pm
-
Note: Anyone can put this tutorial on their website/blog/etc as long as they credit me and link it here. You probably want to include the example programs as well. ;)
First, Clarifications:
-Can be used for RPGs
-Harder to use for platformers, but probably doable
-Allows for 255 different types of tiles in one map (more than enough. :P)
-Easy map switching
-Implemented smoothscrolling in example can be taken out.
-Easily convertible to Greyscale
-This isn't the best code, if you can optimize it go ahead, I just can't explain it well if its too optimized. ;)
-I left out a couple of "0C"s in the data, I could leave out more, I know. :P
-All example code is from the example program unless said otherwise.
Now, for the Tutorial:
Store your sprite data:
I find it easiest to store the Character sprites first. Point the first one to Pic1 and let the rest be relative to that pointer.
After that, point the "ground tile" to Pic0. This tile will be represented by "00" later in the data. This tile is also the one you can always walk on.
The other tiles will also be relative to this pointer, increasing by 8 to get to the next tile. This is more organized if you comment above each piece of data, saying what it is and what number it is. Remember to count in Hex here.
:.CHARACTER
:.HEADFRONT
:[7E7E99A5A5423C42]→Pic1
:.BODYFRONT
:[81A5A5A5425A6666]
:[81A5A5A5425A6760]
:[81A5A5A5425AE606]
:
:.HEADRIGHT
:[3C7EF1C585423C42]
:.BODYRIGHT
:[4A4A45452624241C]
:[4A4A45452654B2EC]
:[4A4A45252624241C]
:
:.HEADLEFT
:[3C7E8FA3A1423C42]
:.BODYLEFT
:[5252A2A264242438]
:[5252A2A2642C4A76]
:[5252A2A464242438]
:
:.HEADBACK
:[7E7EB9B191423C42]
:.BODYBACK
:[81A5A5A5425A6666]
:[81A5A5A5425A6760]
:[81A5A5A5425AE606]
:
:
:.STORE YOUR SPRITE DATA FIRST, I'M ASSUMMING YOU WANT MONOCHROME SPRITES
:.EXAMPLE SPRITES
:.GROUND TILE,0 THIS IS THE NUMBER THAT WILL REPRESENT THE TILE
:[00A04000000A0400]→Pic0
:
:.TREE,1
:[186689A14A3C2442]
:
:.HOUSE,2,3,4,5,6,7,8,9,A SOME OBJECTS NEED MORE THAN ONE TILE, AND THE A IS 10 IN BASE 16
:[03060A1A2A6AAAAA]
:[FF00000000000000]
:[C060505854565555]
:[ABACABB4A8D2A5C2]
:[FF00FF000000007E]
:[D535D52D154BA543]
:[407F407F407F403F]
:[8181A1A1818181FF]
:[02FE02FE02FE02FC]
:
:.PATH,B
:[8181818181818181]
:
:.BLACK BOUDARIES,C
:[FFFFFFFFFFFFFFFF]
Next, keeping the number for each tile in mind, write them out and lay it out like a map, as in:
:.MAP DATA, REMBER THOSE NUMBERS? ADD 0's RIGHT BEFORE THEM, AND STORE THEM TO A POINTER
:[0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C]→GDB1
:[0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C]
:[0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C]
:[0C0C0C0C010101010101010101010101010101010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000203040000000000000000010C0C0C0C]
:[0C0C0C0C010000000506070000000000000000010C0C0C0C]
:[0C0C0C0C0100000008090A0000000000000000010C0C0C0C]
:[0C0C0C0C01000000000B000000000000000000010C0C0C0C]
:[0C0C0C0C01000000000B000000000000000000010C0C0C0C]
:[0C0C0C0C01000000000B000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010000000000000000000000000000010C0C0C0C]
:[0C0C0C0C010101010101010101010101010101010C0C0C0C]
:[0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C]
:[0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C0C]
Looking back, remember the "0C"s are boundaries, "01"s are trees, and "00"s are ground tile, etc.
Too keep it organized, I suggest entering the data for each row on a separate line. Point the first one to GDB1, and let the rest be relative.
When you enter another map, point it to a different GDB, and when you switch maps, Copy a map to a temp pointer, such as GDB0, and just always use GDB0 when mapping.
<hr>
Movement engine:
Keep in mind that this engine is written such that your character stays in the same location on screen, and the map moves around him.
Zero the pointers you need to be 0 first
:.P AND Q ARE THE LOCATION OR THE TOP CORNER OF THE MAP DATA
:0→P→Q→V→H→I→J→θ→{r1}
The {r1} is the one in VARS>Y-VARS>Polar>r1, its the variable telling how much the character pointer should add to to display a sprite facing the direction your moving.
The P and Q are the "psuedo-coordinates" of the top corner of the screen on the map data. We're basically pretending its an array. So P=0 and Q=0 would correspond to the tile in the top left corner being a "0C" tile, or, a black one. And the rest of the tiles shown on the screen will be relative to that. Just look at the "array", and go down Q rows and go right P bytes, a byte being two digits.
V, H, I, and J are just variable to make sure each time you press a arrow key, you only go to a direction 8 pixels at a time, but with smooth scrolling. The smooth scrolling will be better explained later on.
:Repeat getKey(15)
:
:Z→Y
:
:Q*24+P+126→Z
:
:.P+(getKey(3) and (({Z+1+GDB1}=0) or ({Z+1+GDB1}=11)))-(getKey(2) and (({Z-1+GDB1}=0) or ({Z-1+GDB1}=11)))→P
:
:.Q*24+P+101→Z
:.Q+(getKey(1) and (({Z+24+GDB1}=0) or ({Z+24+GDB1}=11)))-(getKey(4) and (({Z-24+GDB1}=0) or ({Z-24+GDB1}=11)))→Q
:
:If getKey(3) and (I=0) and (J=0) and (({Z+1+GDB1}=0) or ({Z+1+GDB1}=11))
:1→I
:32→{r1}
:End
:If getKey(2) and (I=0) and (J=0) and (({Z-1+GDB1}=0) or ({Z-1+GDB1}=11))
:0-1→I
:64→{r1}
:End
:If getKey(1) and (I=0) and (J=0) and (({Z+24+GDB1}=0) or ({Z+24+GDB1}=11))
:1→J
:0→{r1}
:End
:If getKey(4) and (I=0) and (J=0) and (({Z-24+GDB1}=0) or ({Z-24+GDB1}=11))
:0-1→J
:96→{r1}
:End
:
:If getKey(1) or (getKey(2)) or (getKey(3)) or (getKey(4)
:θ+1→θ
:Else
:0→θ
:End
:
:H+I+I→H
:V+J+J→V
:
:If H-8=0 or (H+8=0
:P+I→P
:0→H→I
:End
:If V-8=0 or (V+8=0
:Q+J→Q
:0→V→J
:End
:
:.If Y≠Z
:sub(MAP)
:.End
:
:Pt-Off(40,32,Pic1+8+(θ/4^2*8+8*(θ≠0))+{r1}
:Pt-Off(40,24,Pic1+{r1}
:
:DispGraph
:
:End
The parts that are commented out are for scrolling by 8 pixels at a time (i.e. not smooth scrolling) Uncomment those and comment/delete the If clauses with getkey(1-4) in them. (but not the one that involves storing things into theta)
Smooth Scrolling:
H and V are constantly being incremented by I and J respectively. When you aren't moving, I and J are 0, when you move, I and J change to (-)1 depending where you're going. When H or V equal 8, they get reset to 0 and 8 is added/subtracted to/from P or Q, depending on whether you went Horizontally or Vertically.
Collision detection:
Collision detection is a simple matter of finding out where you are on our "array" and checking whats above, below, and beside you. to find the number of bytes you are away from GDB1, you would take Q, multiply it by you "array's" width, add P, and add 101, in this case, since that gets you from the top corner of the screen to the place where your body is. Now, just check if {Z (the variable with your distance from GDB1) plus GDB1 +/- 1/[width of your array]} To check to your left/right, +/- 1, to check above and below, +/- 24, in this case, that being the width of our "array."
<hr>
Map Drawing
You may have noticed the "sub(MAP)" in the above code, calling the subroutine "MAP."
The map routine is very simple. Use the vars P and Q to find the distance from GDB1 to the top left corner of your screen, as shown in below source. And then use two for loops to increment by 1 to find the next tile, until you reach 12 tiles, and then skip to the next line, and display 12 tiles, and display 8 rows of twelve tiles.
:Lbl MAP
:
:Q*24+P→Z
:
:ClrDraw
:For(B,0,9
:For(A,0,13
:Pt-On(A*8-8-H,B*8-8-V,{B*24+A+Z+GDB1}*8+Pic0
:End
:End
Attached below is a screenie of the Example program and the source/executable
-
I didn't read all of it yet, but this is awesome, just pure awesome, I'm gonna learn tilemapping now (which I never learnt).
-
thanks, if its a bit unclear, just ask in this thread, and I'll elaborate and probably edit the first post to clarify. ;)
-
:.P+(getKey(3) and (({Z+1+GDB1}=0) or ({Z+1+GDB1}=11)))-(getKey(2) and (({Z-1+GDB1}=0) or ({Z-1+GDB1}=11)))→P
:
:.Q*24+P+101→Z
:.Q+(getKey(1) and (({Z+24+GDB1}=0) or ({Z+24+GDB1}=11)))-(getKey(4) and (({Z-24+GDB1}=0) or ({Z-24+GDB1}=11)))→Q
:
This is my first question, why are these as comments?
Also, what does Pt-Off does?
:Pt-Off(40,32,Pic1+8+(θ/4^2*8+8*(θ≠0))+{r1}
:Pt-Off(40,24,Pic1+{r1}
Like in here.
-
Those are commented so you guys have an option.
The parts that are commented out are for scrolling by 8 pixels at a time (i.e. not smooth scrolling) Uncomment those and comment/delete the If clauses with getkey(1-4) in them. (but not the one that involves storing things into theta)
;)
Pt-Off is Pt-on, but it overwrites everyting behind it, so if you had
:Pt-on(0,0,[FFFFFFFFFFFFFFFF]
:Pt-off(0,0,[0000000000000000]
:Dispgraph
It would not show anything.
-
1. /facepalm, read the text and the code;
2. Thanks much for the Pt-Off.
-
Oh thanks for posting this. This might be useful if I eventually coded again. Could you maybe do one with half-bytes/nibbles tilemapping format?
-
Wow, this is cool ;D
Is there a way to make this work with height/width that varies in different levels (reading from an appvar stored row-by-row)?
-
Nice tutorial Yunhua!
I have one thing you should probably mention, that is that you can also use 'Data(' to input maps, some people might find this more convenient.
-
Wow, looks great. Wonderful job, yunhua! ;D
-
Thanks guys! As for nibbles, I'm not very good with those yet, but I'll probably look in to those anyway. But if I used nibbles, wouldn't I be limited to like 16 different tiles? D:
-
Indeed, but most dungeons won't require more than 16 anyway, so people could simply use tile palettes.
-
it says delete if clasuse made out of getkey(1)~getkey(4) except for theta one.
Which part exactly should I delete? ???
just the if one itself?
-
The ones where its like:
:If getkey(1) and [some other conditions]
:blah
:End
:If getkey(2) and [conditions]
:blah
:End
delete those, from getkey(1)-getkey(4), but don't deleted the one involving storing into theta.
-
:Lbl MAP
:
:Q*24+P→Z
:
:ClrDraw
:For(A,0,139
:Pt-On(A^14*8-8-H,A/14*8-8-V,{A/14*24+(A^14)+Z+GDB1}*8+Pic0
:End
:End
'twas bored, so I made it run on a single loop. I think it's actually smaller, but slower. No idea.
-
This deserves 255 thumbs up. Anyone with AXE should read this, it's just practically perfect. Just wish collisions were in the code- Did I miss them in there?
-
Thanks! and yeah, collisions are in there.
Look at the getkey parts of the code, it won't let you step on anything that isn't 0 in the data. You can also code in other exceptions. ;)
-
Thanks! and yeah, collisions are in there.
Look at the getkey parts of the code, it won't let you step on anything that isn't 0 in the data. You can also code in other exceptions. ;)
And thanks for that info. I can start coding now.
-
Glad I could help. ;)
You should post about your project soon. ;)
-
Very good for those who are new to scrolling maps.
Just one question: why is the last row of your map longer than the others ? Because I would like to make scrolling maps and if this extra 0C is necessary, I have to put one too (but I'll do my own routine because I don't want exactly this result).
-
Just one question: why is the last row of your map longer than the others ? Because I would like to make scrolling maps and if this extra 0C is necessary, I have to put one too (but I'll do my own routine because I don't want exactly this result).
I assume that it's a typo; I don't see a reason for it either.
-
how could you make a kind of map file format that could be created in a level editor and loaded as an external file?
btw great work on the example
-
All you have to do is read from an appvar. The map editor creates an appvar, stores the map inside. the program gets the location, and uses that pointer.
-
Maybe it'd be helpful to include a tile-mapping program/utility with the source code and detailed documentation. Then again, they're fairly easy to write.
-
there's one attached on the first post.
-
Oops. My bad.
-
So i used your character sprites and ended up with some messed up looking dude...
x.x
(i'd put a screenshot but i'm a noob and idk how to do that)
-
Wabbitemu is a program I think is normally used for screenies.
(I also think code example might help more :P)
-
Make sure you're using dispgraph(little r thingy) for the body.
-
fixed it.
instead of
:Pt-Off(40,32,Pic1+8+(θ/4^2*8+8*(θ≠0))+{r1}
:Pt-Off(40,24,Pic1+{r1}
I had to use
:Pt-Off(40,32,8+(θ/4^2*8+8*(θ≠0))+Y+Pic1
:Pt-Off(40,24,Y+Pic1
and I interchanged all instances of {r1} with Y
Also, I have Wabbitemu, just don't know how to upload the screenie to here.
The code I was using was the exact same as the tutorial.
-
I have a question. If you want to change the GDB easily by changing one row instead all the rows how can you do that because then I can make like you can have a building being built.
-
"GDB" is nothing but a name. You could have put "°TheMap" or "Str12" instead of "GDB1". I just say that because some people confuse pointers with objects and feel like they're declaring some structure when doing →GDB1.
And changing an element is easy. If you want the first byte in the free RAM area starting at L1 to be 1, you do 1→{L1}, right ?
Well if you want your 58th byte in the RAM area that is your map starting at GDB1 to be 18, you do 18→{58+GDB1}.
And if you can change each element, you can change tows, etc.
Just note that, as I said, that works everywhere in RAM (even in places you shouldn't write to) but nowhere else, so if you compiled your code as an app, it will be run from Flash and you "can't" modify anything there, so you'll have to use workarounds like appvars, or to copy data in free RAM areas first. But if you didn't compile as an app, forget that last sentence.
-
But if you make the program edit it's data, just make sure that you can also save it back, because if you don't, all the changes will remain if the player starts a new game.
-
I have another question. Is every two character in the gdb as one byte or is it 2?
-
Two characters within square brackets are compiled to 1 byte (each hexadecimal character represents 4 bits), but in the source code, they are 2 bytes.
-
I have another question. Is every two character in the gdb as one byte or is it 2?
I see you didn't read what I wrote.
"In the GDB" doesn't mean anything, the GDB is a number, a pointer, not an object with numbers inside.
And every pointer points to one byte, but you can read 2 bytes at once, or 4 if you want, or interpret a sequel of 11 bytes as a string, etc, they don't have a size, it is just you deciding when putting them in your program what they represent.
-
I have another question. I converted my map data to {C}, and then I do [21]→{127+C} and after that I write [22]→{128+C} but then when I run the program it shows me a picture of something completely different.
-
You still didn't read, or you didn't understand and did not ask.
First of all, "I converted my map data to {C}" really doesn't mean anything. Not just because we're in Axe, this time. I don't think that could mean something in another language.
Then, "[22]→{127+C}" tries to store a pointer to [22] (which is not the hex value 22 but a 2-byte number) in the one byte located in 127+C. Same with "[22]→{128+C}".
So I think you didn't "convert" anything (because there is no such thing as "conversion" in Axe), then you stored random numbers in two bytes, so I don't see why your picture would not be completely different.
Would you mind sharing the complete code ?
-
Do I have to type the code out or is there an easier way to do it?
-
You can transfer your code to the computer (which would make a backup of your code, useful too) then open it with TokenIDE (http://ourl.ca/6647) (doesn't need any installation (except the .NET Framework if you don't have it)) and copy-paste the content. Instead of using TokenIDE, you can also use TI-Editor, which is an online tool for that, but this is a bit weird to read the produced code because it is a Basic IDE, with Basic tokens, not Axe ones, while TokenIDE supports both languages.
Or if you are lazy, you can also just attach the code to your post, but you should know that other people are lazy too (me in particular), and find it harder to download than just read :P
-
thanks! this really helped me ;D
-
Here is the code:
.STARCRAF
.CHARACTER
[0000000000000000]->Pic1
[FF818181818181FF]
.STORE YOUR SPRITE DATA FIRST, I'M ASSUMMING YOU WANT MONOCHROME SPRITES
prgmSTARCRAD
.MAP DATA, REMBER THOSE NUMBERS? ADD 0's RIGHT BEFORE THEM, AND STORE THEM TO A POINTER
[020202020202020202020202020202020202020202020202]->GDB1
[020202020202020202020202020202020202020202020202]
[020202020202020202020202020202020202020202020202]
[020202020101010101010101010101010101010102020202]
[020202020100000000000000000000000D0D0D0102020202]
[020202020100000000000000000000000D0D0D0102020202]
[020202020100000000000000000000000D0D0D0102020202]
[020202020100000002030400000000000000000102020202]
[020202020100000005060700000000000000000102020202]
[020202020100000008090A00000000000000000101010202]
[0202020201000000000B0000000000000000000000000202]
[0202020201000000000B0000000000000000000101010202]
[0202020201000000000B0000000000000000000102020202]
[020202020100000000000000000000000000000102020202]
[020202020100000000000000000000000000000102020202]
[020202020100000000000000000000000000000102020202]
[020202020100000000000000000000000000000102020202]
[0202020201000000000000000000001B18191A0102020202]
[020202020101010114151614151614151C1D1E1F02020202]
[020202020202020202020202020202020202020202020202]
[02020202020202020202020202020202020202020202020202]
.ENGINE
.P AND Q ARE THE LOCATION OR THE TOP CORNER OF THE MAP DATA
0->P->Q->V->H->I->J->theta->{r1}->G->K->L->M->W
GDB1->C
rand^20+1->D
Repeat getKey(15)
Z->Y
Output(1,1,P>Dec,[i]
Output(1,5,Q>Dec,[i]
Q*24+P+126->Z
.P+(getKey(3) and (({Z+1+GDB1}=0) or ({Z+1+GDB1}=11) or ({Z+1+GDB1}=13)))-(getKey(2) and (({Z-1+GDB1}=0) or ({Z-1+GDB1}=11) or ({Z-1+GDB1}=13)))->P
.Q*24+P+101->Z
.Q+(getKey(1) and (({Z+24+GDB1}=0) or ({Z+24+{L1}}=11) or ({Z+24+{L1}=13)))-(getKey(4) and (({Z-24+{L1}}=0) or ({Z-24+{L1}}=11) or ({Z-24+{L1})))->Q
If getKey(3) and (I=0) and (J=0) and (({Z+1+C}=0) or ({Z+1+C}=11) or ({Z+1+C}=13) or ({Z+1+C}=9))
1->I
32->{r1}
End
If getKey(2) and (I=0) and (J=0) and (({Z-1+C}=0) or ({Z-1+C}=11) or ({Z-1+C}=13) or ({Z-1+C}=9))
-1->I
64->{r1}
End
If getKey(1) and (I=0) and (J=0) and (({Z+24+C}=0) or ({Z+24+C}=11) or ({Z+24+C}=13) or ({Z+24+C}=9))
1->J
0->{r1}
End
If getKey(4) and (I=0) and (J=0) and (({Z-24+C}=0) or ({Z-24+C}=11) or ({Z-24+C}=13) or ({Z-24+C}=9))
0-1->J
96->{r1}
End
If getKey(1) or (getKey(2)) or (getKey(3)) or (getKey(4)
theta+1->theta
If ({Z+24+C}=13) and ((L!=P) or (M!=Q))
D-1->D
P->L
Q->M
End
If ({Z-24+C}=13) and ((L!=P) or (M!=Q))
D-1->D
P->L
Q->M
End
Else
0->theta
End
H+I+I->H
V+J+J->V
If H-8=0 or (H+8=0
P+I->P
0->H->I
End
If V-8=0 or (V+8=0
Q+J->Q
0->V->J
End
If getKey(54) and (G=0) and (K=0)
1->G
End
If (getKey(54)=0) and (G=1) and (K=0)
1->K
End
If getKey(54) and (K=1)
0->K
0->G
End
If K=0
Pause 80
End
.If Y!=Z
sub(MAP)
.End
Pt-Off(40,32,Pic1+8
.Pt-Off(40,24,Pic1+{r1}
DispGraph
If getKey(55)
[20]->{127+C}
[21]->{128+C}
End
End
Lbl MAP
Q*24+P->Z
ClrDraw
For(B,0,9
For(A,0,13
Pt-On(A*8-8-H,B*8-8-V,{B*24+A+Z+C}*8+Pic0
End
End
.This is prgmSTARCRAD
..DATA
.GROUND TILE,1
[0000000000000000->Pic0
.EMPTY SPACE,2
[FFFFFFFFFFFFFFFF
.RIGHT BAR,3
[0101010101010101
.LEFT BAR,4
[8080808080808080
.CRYSTAL,5
[E395994A4C24261E
.LEFT VESPENE GAS,6
[001C223E2241C03F
.RIGHT VESPENE GAS,7
[0038447C820183FC
.TOP LEFT SIDE,8,9,A,B
[FF808080EAFF8098
[FF000000AAFF0030
[FF000000AAFF00F8
[FF000000AAFF00F8
.BOTTOM LEFT SIDE,C,D,E,F
[A79F807F00000000
[C9F000FF00000000
[55F800FF00000000
[54F800FF00000000
.TOP MIDDLE SIDE,10,11,12,13
[FF00000055FF007C
[FF00000055FF007C
[FF00000055FF007C
[FF00000055FF007C
.BOTTOM MIDDLE SIDE,14,15,16,17
[AA7C00FF00000000
[AA7C00FF00000000
[AA7C00FF00000000
[AA7C00FF00000000
.TOP RIGHT SIDE,18,19,1A,1B
[FF000055FF00001F
[FF000055FF00001F
[FF000055FF00000C
[FF010157FF010119
.BOTTOM RIGHT SIDE,1C,1D,1E,1F
[2A1F00FF00000000
[AA1F00FF00000000
[930F00FF00000000
[E5F901FE00000000
.BARRACK,20,21,22,23,24,25,26,27,28,29,2A,2B,2C,2D,2E,2F,30,31,32,33
[0C0C0C0C0C0C0C0D
[0000000000001FE0
[000000000000F807
[30303030303030B0
[0E10204C8D8D8D8C
[000738C03C4381C2
[00E09C4781C23C03
[70080432B1B1B131
[CCECFCFEFFFFFFDF
[3907000000E0FFFF
[1CE000000007FFFF
[33373F7FFFFFFFFD
[D7D5D5D5D5D55535
[FFDF404C52524C40
[FFFD8199A5A59981
[F5D5555555555556
[0F00000000000000
[E01F000000000000
[83FC000000000000
[F800000000000000
.UFO LAB,34,35,36,37,38,39,3A,3B,3C,3D,3E,3F
[0000000F708080F0
[03047890100C0300
[C0201E090830C000
[000000F00E01010F
[FFFFE7C3C3E7FF7C
[80FFFFE7C3C3E77F
[01FFFFF3E1E1F37F
[FFFFE7C3C3E7FF1F
[090A0A0A0A0A0A00
[FF01010101010100
[4040404040404000
[C828282828282800
-
Please use the [code ][/ code] tags (without the spaces) to put your code in.
-
I figured out my problem I did [21]→{C} instead of 21→{C}