I've went through the tutorial, quite confusing but very amazing C:
I seem to not understand getKey's too well, the values i'm fine with, just:

X+getKey(3
min(-getKey(2,95→X

seems very different from what I know x_x
As for text displaying, using Text( and getKey to move the character around, moving up and down increments only by 1 pixel while left and right seem to move 4 or 5 pixels. So to keep my character from going off the screen, i'd have to set the limits to min(-getKey(2,23→X and min(-getKey(4,58→Y.
I learned that Output just changes the font, now. (After many pointless attempts to get text on the screen xD)
And i'm still not too sure how I could use Hexidecimal to display sprites. (I know how to make them, but how would I use the command?)

Any examples to show me how a few of these things work? c:

The last thing I want to learn is the particles, which I can't wait to play with Very Happy
Hmm, I should update the movement code, then. This might make more sense:

Code:

X+getKey(3:-getKey(2
If <96
→X

You do not need to check if it goes below zero because if it goes past 0, it wraps back around to 65535. As to the Text( command, the default font draws to 24 columns and it uses a custom Grammer font that is 4x6. Output( doesn't actually change the row, rather, it changes the font type. For example

Code:

Output(0     ;set to the default font (writes to aligned coordinates)
Output(1     ;set to the variable size font (writes to pixel coords)
Output(2     ;Use the default fixed size font, but write to pixel coordinates
Output(3,ptr ;Use Omnicalc/Batlib style fonts

All of those can take a ptr argument that points to a custom font, by the way.

To display a sprite that is encoded as hexadecimal data, you will want to add 8 to the Method argument. For example, Method=2 will draw the sprite with XOR logic. So to use hex data, use Method=10. For example:

Code:

Lbl "Sprite→S   ;get the pointer to the line following .Sprite
0→X→Y
Repeat getKey(15
Pt-Off(10,S,Y,X,1,8
DispGraph
Pt-Off(10,S,Y,X,1,8
Repeat getKey
End
X+getKey(3:-getKey(2
If <88
→X
Y+getKey(1:-getKey(4
If <56
→Y
End
Stop
.Sprite
3C4281818181423C

I did not test that code, so I am sorry if it has mistakes.
Nope, no mistakes at all!
I'm amazed by the pointers, though Surprised
I can store a string into S, and recall it as a value. (I think..)
Why call Pt-Off( twice..?
If I had multiple pointers like .SPRITE, would I put a "return" at the end of them?
And onto particles, how do they work..?
How could I add velocity to them or make them form like in your example program, making them seem like water..?
Also, could you explain what XOR login is? I might know, but i'm not sure..
God i'm excited x3
hellninjas wrote:

I can store a string into S, and recall it as a value. (I think..)

In reality, you are just storing a pointer to the string. Pointers simply tell Grammer where the actual data is at Smile

hellninjas wrote:
Nope, no mistakes at all!
Why call Pt-Off( twice..?

I used XOR logic, so calling it twice leaves no net effect on the screen. Try adding a DispGraph after the second Pt-Off( and you will see it erasing itself.

hellninjas wrote:
Nope, no mistakes at all!
If I had multiple pointers like .SPRITE, would I put a "return" at the end of them?

I am not sure what you mean .__. .Sprite is just a label in Grammer, and when you use Lbl to search for the label and return a pointer, it just points to the data on the next line. The Pt-Off( command knows how much data to read based on the size inputs.
hellninjas wrote:
Nope, no mistakes at all!
Also, could you explain what XOR login is? I might know, but i'm not sure..

Basically, if a pixel is ON in the sprite, it inverts it on the screen. If it is OFF in the sprite, it does nothing to the screen.

hellninjas wrote:
Nope, no mistakes at all!
And onto particles, how do they work..?
How could I add velocity to them or make them form like in your example program, making them seem like water..?

The particles follow a simple ruleset. For example, the sand/water looking one follows the rules:
Move down if the path is not obstructed. If it is, choose left or right and move there if it isn't obstructed. If it is obstruct, go the other way. If that is still obstructed, don't move. So to define that rule (if you didn't know it is one of the two built in rules):

Code:

P▶Ry(2,"D,LR    ;2 means a custom rule set, D=Down, LR=Left/Right

The way Partex2 or Partex3 does it, it firsts creates a buffer using a temp program. Each particle takes 2 bytes, and there is a 2-byte counter at the start of the buffer. To create a buffer that can hold up to 2000 particles, make it 4002 bytes:

Code:

Send(4002,"VP()
P▶Ry(2,"D,LR

The V means it is a temp program, P() is just a weird name to make sure you aren't overwriting an actual program that already exists.

Now you have a cleared buffer and your rule is defined. Now you just need to add particles. The easiest way is like this:

Code:

P▶Rx(Y,X

That will add a particle at coordinates (Y,X), but you won't see anything special until you use the R▶Pθ( command. This is the command that goes through the particle buffer, drawing all of the particles and moving them around according to the rules. Then to see the lovely work, use DispGraph. So putting it all together:

Code:

Send(4002,"VP()
P▶Ry(2,"D,LR
0→X→Y
Repeat getKey(15
If getKey(9
P▶Rx(Y,X
R▶Pθ(
Pxl-Change(Y,X    ;a cursor
DispGraph
Pxl-Change(Y,X    ;re-invert to leave no change on the screen
X+getKey(3:-getKey(2
If <96
→X
Y+getKey(1:-getKey(4
If <64
→Y
If getKey(54        ;2nd
Pxl-On(Y,X
If getKey(56        ;Del
Pxl-Off(Y,X
End
Stop

Again, that is untested, but it should allow you to move a cursor around, draw with [2nd] and [Del], drop particles with [Enter] and exit with [Clear].
Xeda112358 wrote:
I am not sure what you mean .__. .Sprite is just a label in Grammer, and when you use Lbl to search for the label and return a pointer, it just points to the data on the next line. The Pt-Off( command knows how much data to read based on the size inputs.

I meant like..

Code:
Lbl "SPRITE->S
Lbl "OTHER->F
blah code blah blah
.SPRITE
FFFFFFFFFFFFFFFF
//Return would go here
.OTHER
blahblah

But you already answered that, it will only point to the line directly after Very Happy

And wow, particles are much easier than they look o_o
What other things are possible with the custom ruleset? :3
Not much, unfortunately. If you allow particles to move up if they have no other place to go, they exhibit capillary actions if you give them thin tubes to follow. Otherwise, there isn't much that can be done. They are a lot simpler than what they could be XD So the other rule would be:

Code:

P▶Ry(2,"D,LR,U

Both of the rules I have shown you so far are defaults, so you can use these instead:

Code:

P▶Ry(0
P▶Ry(1

Being able to change the rules is mostly useful if you want to change the direction of movement. For example, if you switch D with U and vice versa, particles will move up instead of down. If you create multiple particle buffers, you could set a rule for each one and see how they interact together.
And how would I make multiple buffers & display them?

Curious if I can make a fire kind-of effect, but that means deleting the particles as well, how would I give them a time limit for how long each one could exist?

(Thanks a bunch for the speedy replies, btw :3)
Oh, you can do something like this:

Code:

Send(1000,"VP()→P
Send(1000,"VQ()→Q
Send(1000,"VR()→R
Send(1000,"VS()→S

Then replace the line in the above program 'R▶Pθ(' with something like this:

Code:

P▶Ry(0
R▶Pθ(P
P▶Ry(1
R▶Pθ(Q
P▶Ry(2,"U,LR
R▶Pθ(R
P▶Ry(2,"U,LR,D
R▶Pθ(S

That should run particles from custom buffers with custom rules for each, but I've actually not tried it yet.

To delete them is a pain since it would require scanning the particle buffer for a given set of coordinates and then deleting it properly. Grammer automatically removes particles that go off screen, so I typically just let the particles fall off if I want them gone.
This is amazing :3

I create two buffers of particles that are counter-acting each other, pushing back in a small tube and it looks kewl c:

But now onto other things!

Storing data into Pic1 etc,..
How to make/store/recall a matrix?
And how to make, display, and edit tilesets Surprised
To store data into Pic1 (I am assuming you mean the OS var), you can check if it exists and get a pointer to it:

Code:

Unarchive "GPic1
!If Pic1       ;'Pic1' returns a pointer to Pic1. 0 means it doesn't exist
Send(768,"GPic1   ;create it if it doesn't exist

Now if you want, you can set the picture as your draw buffer using Disp. So:

Code:

Disp Pic1

Now all drawing will occur on Pic1. If you don't want to use this as the default buffer, but you want to draw to it, you can do things like:

Code:

Pxl-On(Y,X,Pic1


As to matrices, Grammer doesn't directly support them, so you will have to make your own matrices. Basically, say you want to make an 8x12 array of bytes. That is 96 bytes, so create an Appvar (or whatever you like) of 96 bytes:

Code:

Send(96,"UAppvar→Z     ;U means it is an appvar

Then if you want every chunk of 8 bytes to be a column, to access element (Y,X):

Code:

(Z+Y+8*X

That reads the byte at the computed address. TO write to the byte:

Code:

int(Z+Y+8*X,<value>

Remember to be careful about the order of math in Grammer !
A question on a falldown game:
How would I make it generate the infinite platforms that the player falls through?
And i'm sure i'd use Tangent for moving the platforms.
I'm wondering that if I could figure this out, that I could make a copter game as well :3
Yes, I personally prefer to use Tangent( to shift the screen. While you are shifting the screen, keep a counter running so that you know when to draw the next platform. This is actually the second time this particular question has been asked, so I actually have info ready at hand XD I assume this is what you mean to make?

The code for that program was:

Code:

:.0:Return
:31→Y
:47→X
:0→L
:30→M
:1→P
:ClrDraw
:While Y=abs(Y
:Line(0,59,5,96,1
:randInt(0,86
:Line(,59,5,12,2
:1→F
:For(A,1,M
:getKey→K
:If K=10
:Full
:If K=11
:Full0
:K=3
:-K=2
:+Ans+X
:If <86: and !Line(Ans,Y,6,6,15
:→X
:If Y<52: and !Line(X,Y+6,1,6,14
:IS>(Y
:Repeat 1
:Return→Z
:Line(X,Y+1,4,6,2
:Line(X+1,Y,6,4,2
:End
:DispGraph
:prgmZ
:If P xor 1→P
:Tangent(1,8:Y-!!Line(X,Y,7,6,15→Y
:End
:If L+1→L=5: and M>14
:Then
:0→L
:M-1→M/30
:If θ': and P>0
:P-1→P
:End
:End
:Stop

That uses some more advanced techniques. For example, this chunk of code:

Code:

:Repeat 1           ;This means the code won't repeat. Why would we do that?
:Return→Z           ;Returns a pointer to the next line of code
:Line(X,Y+1,4,6,2   ;Draws a rectangle, inverted
:Line(X+1,Y,6,4,2   ;Draws an inverted rectangle
:End                ;Ends the Repeat loop
:DispGraph          ;Updates the LCD
:prgmZ              ;Calls the code at pointer Z as a subroutine o_O

Subroutines must end with an End. So must Repeat loops. So basically, you can hack the Repeat function to create in-line subroutines, which is rather awesome and useful. On top of that, you can use Return to get a pointer which is much faster than using Lbl.
Oh no, that's a lot o_o

Oke, questions x3
I know abs( means absolute, but what does it do exactly, and how could I use it?
In
Xeda112358 wrote:

Code:
:Line(,59,5,12,2

How does that section of Line( work?
What are the variables L, M, and P for?
How do use Full or Full0 :C ?
How was the IS>(Y command used?
What does this line of code do?

Code:
:If θ': and P>0
:P-1→P
:End


And lastly, why must I ask so many questions? x_x
hellninjas wrote:

I know abs( means absolute, but what does it do exactly, and how could I use it?
Grammer doesn't actually have negative numbers. When you subtract a value from zero, you are basically doing 65536-number. So for example, 0-2 yields 65534. What Grammer does with abs( is it checks if the number is greater than or equal to 32768. If it is, it negates it by doing 65536-num, otherwise, it leaves it alone. It works, too. You can test it by doing something like this:

Code:

.0:Return
ClrDraw
Text('0,0,abs(3-16
DispGraph
Stop

You will see it display 13 instead of 65523.
hellninjas wrote:

In
Xeda112358 wrote:

Code:
:Line(,59,5,12,2

How does that section of Line( work?

Because the argument is omitted, Grammer uses the last computed value. Since the previous value was a value from randInt(, the X value was the result of that command.

hellninjas wrote:

What are the variables L, M, and P for?

L, M, and P are all counters of some sort.
P toggles between 1 and 0, and when it is not 0, the screen is shifted up.
L is incremented every time a new barrier is drawn at the bottom of the screen. Every 5th increment, it is reset and M is decremented. M controls how quickly new barriers appear. It is a convoluted system meant for speed.

hellninjas wrote:

How do use Full or Full0 :C ?

The Full command is located in the Mode menu. It simply sets the calculator to 15MHz. Full0 sets the calculator back down to 6MHz.

hellninjas wrote:

How was the IS>(Y command used?

It's intended use is to read the byte at Y, then increment Y. In this case, though, it is just a fast/small way to increment Y.

hellninjas wrote:
What does this line of code do?

Code:
:If θ': and P>0
:P-1→P
:End


θ' is often used for extra information about math. For example, it holds overflow from addition, subtraction, and multiplication, and holds the remainder from a division. In this case, that should have actually been:

Code:
:If !θ': and P>0
:P-1→P
:End

But it would not have caused any problems.
hellninjas wrote:

And lastly, why must I ask so many questions? x_x
I dunno Razz It's fine, though Smile
Would colliding a sprite with particles be possible? :O
Adding something like buoyancy..?
Well, you would have to do it manually with the sprite and it could be complicated:


  • Draw the sprite on the main buffer and execute one particle cycle.
  • Now check the sprite for collision detection on the main buffer, basically using particle rules.
    • First check to see if the sprite can move down. If it can, then good, move down. Otherwise, go to the next step:
    • Check a random direction, left or right, see if the sprite is not blocked. If it isn't blocked, move in that direction, else check the other direction. If that is still blocked, then your sprite stays where it is.


This will treat your sprite as a rather large particle to interact with others. If you use the basic particle rule "D,LR", your sprite will stay on top of the particles, maybe moving down a little bit. If you use the 'boiling' particle effect 'D,LR,U' (which exhibits capillary action) you will notice it exhibits surface tension, too. A sprite with a flat bottom will most likely float, a sprite with a pointed bottom will sink right through the mass of particles.

But yeah, I never added in sprite pixel testing, so it will be a pain in the butt to do quickly.
Are D, LR, and U the only custom rulesets at the moment..?

How would acceleration work, and collision with pixels or sprites (Both normally and with acceleration)?

Is there any way to give the particles their own gravity, so as bouncing off things, maybe? (Explosions?)

EDIT: Are there any features with Pxl-Test( that I could use? Surprised

ANOTHER EDIT Very Happy : I'm having a bit of trouble displaying sprites x_x
I have :Lbl "SPRITE→S setup to a .SPRITE:FFFFFFFFFFFFFFFF.
Now I just need to display it, but Pt-Off( 's syntax is different, how would I do it..?

So many questions C:
hellninjas wrote:
Are D, LR, and U the only custom rulesets at the moment..?

Yes, those are all of the custom rules.
hellninjas wrote:

How would acceleration work, and collision with pixels or sprites (Both normally and with acceleration)?
That would have to be done entirely in Grammer code. Have you checked out any of my gravity simulation programs?
What I do there is I have a variable for X and Y velocity, X and Y acceleration, and X and Y position. So we can call those V,v,A,a,X,Y and do something like this:

Code:

Repeat getKey(15
X+V→X
Y+v→Y
If 9200<X+V
-V→V
If 6000<Y+v
-v→v
V+A→V
v+a→v
Y/100→C
X/100→B
Line(,C,4,,2
DispGraph
Line(,C,4,,2
End

That doesn't check for collisions, though. To do that, just check if there are any ON pixels between the old position and the new position, instead of using those If statements.

hellninjas wrote:

Is there any way to give the particles their own gravity, so as bouncing off things, maybe? (Explosions?)
There isn't enough code space in Grammer for that, sorry. There was at one point a hidden, incomplete feature for handling arbitrary sized objects with gravity and collision detection using the ANOVA( command, but I ended up removing that to add in other features.

hellninjas wrote:

EDIT: Are there any features with Pxl-Test( that I could use? Surprised

It is basically like the BASIC pxl-Test( command except that it won't throw an error if you do out-of-bounds tests and you get results for the last column and row of pixels. Out of bounds tests return 0, but you can set a mode using the Fix command (I think it is Fix 16) so that OOB pixel tests return 1 instead.
hellninjas wrote:

ANOTHER EDIT Very Happy : I'm having a bit of trouble displaying sprites x_x
I have :Lbl "SPRITE→S setup to a .SPRITE:FFFFFFFFFFFFFFFF.
Now I just need to display it, but Pt-Off( 's syntax is different, how would I do it..?

The only differences are that you cannot use some drawing methods (DataSwap, grayscale, and masked) and you can draw to pixel coordinates instead. Otherwise, it should be the same. Hopefully I didn't break anything, though :[ Just remember that when using hexadecimal data, you need to add 8 to the drawing method.
Now to tile-mapping, which i'm sure is going to be difficult x_x
How would I create the data for multiple tiles in one Hex string and compress it into an OS variable?
How would I display that onto the screen using the different tiles?
How would I check for collision with the different tiles?
How would I change certain tiles to a new value? (Changing the tile in-game?)
hellninjas wrote:
Now to tile-mapping, which i'm sure is going to be difficult x_x
How would I create the data for multiple tiles in one Hex string and compress it into an OS variable?
Luckily, I just explained a technique to The_Warlord this morning. However, I will expand on that a little more here.

You may have noticed the DataSwap option for drawing tiles with Pt-On(. That will be very useful. In Grammer, the built in tilemap command uses 8x8 tiles, so I will assume that is what you will need. The hex for one tile is 16 characters long, so it is 16 bytes. If you put each tile on a new line, the newline token is an extra byte, so in all, it is 17 bytes per tile for accessing it. Now you need to create an appvar of a given size If you have 32 tiles, you will need 32*8 bytes (so 256):

Code:

Send(256,"UTiles→Z

So now we have created the appvar named Tiles and Z has a pointer to its data. The next step is to draw each tile and then copy its data to the appvar. To do this, we will use the DataSwap option in a clever way-- we will swap the null data in the appvar with the data just drawn on screen. So to put it all together:

Code:

:Send(256,"UTiles→Z
:Lbl "TILES→P
:For(A,0,31
:Pt-On(8,P,0,0,1,8    ;draw the hex sprite
:Pt-On(4,Z,0,0,1,8    ;Use DataSwap to swap the sprite on screen with the data in the appvar
:Z+8→Z           ;next sprite in the appvar
:P+17→P           ;next hex sprite
:End
:Stop
:.TILES
:0000000000000000
:3C4281818181423C
:...

Another way you can do it is with a similar trick but might be a lot easier for you. You can draw 7 8x8 sprites in a column on the graph screen, so you could copy it to the appvar using the DataSwap method as if it were a 56-pixel tall sprite.

hellninjas wrote:

How would I display that onto the screen using the different tiles?

If the pointer to the appvar holding the sprites is in Z, then to display sprite N at X,Y:

Code:

Pt-Off(0,Z+N*8,Y,X

However, Pt-On( is typically used for tiles. It doesn't draw to pixel coordinates, which makes it faster than Pt-Off(, and often better for use with tilemaps. It uses X coordinates 0~11 (like how Output( in BASIC uses 1~16).
If you want to draw a tilemap to these aligned coordinates, there is a pretty high-level command (meaning it makes it easy for the end user to do something complicated):
Pt-Change(0,MapData,TileData,MapWidth,MapXOffset,MapYOffset,TileMethod
You can check out the details in the readme and command reference, but it does all of the math for computing where the tilemap data is, given the offsets into the data and then it draws them to their correct location. On top of that, it is a lot faster than doing it purely in Grammer code.

As a note, Grammer tilemaps are stored by column first, then row. So the first bytes make up the first column, then it moves right, to the next column.
hellninjas wrote:

How would I check for collision with the different tiles?

If you have the data stored in a tilemap, you can compute the location in the tilemap of the corresponding byte. So say your tilemap has a height H and you want to read the tile at Y,X and the tilemap is pointed to by T:
The offset to the column is at X*H
The offset in that column to the row is just Y
So put it all together:
T+Y+X*H
And to read the byte, you simply use:

Code:

(T+Y+X*H

hellninjas wrote:

How would I change certain tiles to a new value? (Changing the tile in-game?)

Continuing from the last question, you can change the tile by doing this:

Code:

int(T+Y+X*H,newvalue
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 2
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement