This is an archived, read-only copy of the United-TI subforum , including posts and topic from May 2003 to April 2012. If you would like to discuss any of the topics in this forum, you can visit Cemetech's TI-BASIC subforum. Some of these topics may also be directly-linked to active Cemetech topics. If you are a Cemetech member with a linked United-TI account, you can link United-TI topics here with your current Cemetech topics.

This forum is locked: you cannot post, reply to, or edit topics. TI-Basic => TI-BASIC
United-TI Archives -> TI-Basic
 
    » Goto page Previous  1, 2, 3 ... 8, 9, 10, 11, 12, 13  Next
» View previous topic :: View next topic  
Author Message
axcho


Active Member


Joined: 09 Nov 2004
Posts: 555

Posted: 24 Jan 2005 04:18:34 pm    Post subject:

Here's a new topic. I want to share some of the uses of complex numbers for coordinates. It is applicable to string coordinates as well because string coordinates can store a point in a single number.

Let's say you are putting the vertical coordinate in the imaginary part, and the horizontal coordinate in the real part. Vertical coordinates increase from top to bottom and horizontal coordinates increase from left to right.

In the first situation, say you want to have a loop that goes in a variable direction, so you don't know which axes it will use (horizontal or vertical or both). It is easy when you store the coordinates in a single number.

Code:
"P=POSITION
"V=VELOCITY
"R=DICE ROLL
"...
randInt(1,6->R
"...
getKey
(.4=fPart(.1Ans))-(.2=fPart(.1Ans))+i((9=iPart(.1Ans))-(7=iPart(.1Ans->V
"...
While R and not(pxlTest(imag(P),real(P
R-1->R
P+V->P
End
"...

I haven't actually tested out this code, but it should get the direction from the keypress and then move the position the amount on the dice roll or until it hits something. Maybe it's not that much easier with complex numbers. But this next part is.

You can rotate the direction (velocity) either 90 or 45 degrees easily with complex number coordinates. To rotate 90 degrees clockwise, just multiply by i. If you want to rotate on a conditional statement, take the coefficient to a power of 0 or 1. Multiplying something conditionally requires taking it to the power of the conditional, while adding something conditionally requires multiplying by the conditional. The following code should rotate depending on a key press.

Code:
"V=VELOCITY
randInt(-1,1)+irandInt(-1,1->V
"...
getKey
Vi^((Ans=26)-(Ans=24->V


It is more complicated to rotate 45 degrees, since the value doubles every time there are two terms in the velocity (a diagonal direction). You have to compensate for this by multiplying by a half whenever there are two terms.

Code:
"V=VELOCITY
randInt(-1,1)+irandInt(-1,1->V
"...
getKey
V(1+i)^((Ans=26)-(Ans=24)).5^(real(Ans) and imag(Ans->V

It looks kind of complicated, but it should work. It would be nice if anyone can find a better way to do this, though.


Last edited by Guest on 24 Jan 2005 04:19:01 pm; edited 1 time in total
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 24 Jan 2005 04:26:18 pm    Post subject:

I've moved this to the Source Code topic, this is too complex to be just a 'trick'.
Back to top
Ray Kremer


Member


Joined: 16 Feb 2004
Posts: 237

Posted: 26 Jan 2005 11:32:39 am    Post subject:

Sure. On the 85/86, complex numbers actually are expressed as ordered pairs.
i.e. -4+7i is (-4,7)
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 29 Jan 2005 06:24:43 pm    Post subject:

Something I came up with to convert numbers to fractions (fairly unoptimized)


Code:
Prompt F,T
DelVar L1
1->I
Repeat T>abs(F-int(F
int(F->L1(I
I+1->I
1/fPart(F->F
End
int(F+.5->N
1->D
For(I,dim(L1),1
N->Z
D+NL1(I->N
Z->D
End
Disp N,"/
D

F is the fraction. T is a tolerance (so put something like .1 or .01) but it is NOT the tolerance to which it is calculated. .01 should be close enough to 0.

Example:
F=pi, T=.1 : 22/7
F=pi, T=.01 : 355/113 <less than a second to finish>
F=pi, T=.001 <caused overflow because numerator was too large>

F=e, T=.01 : 4.738125506E11/1.743058963E11 <about 1 second>

Maybe I should put a limit on how big I gets...

Edit:

Code:
Prompt F,I
I->dim(L1
While I and fPart(F
iPart(F->L1(I
I-1->I
1/fPart(F->F
End
{1,round(F,0
For(J,I+1,dim(L1
{Ans(2),Ans(1)+Ans(2)L1(J
End
DelVar L1Disp Ans(2),"/
Ans(1

F is the fraction. I should probably be around 10, maybe less (even I=1 returns pretty good results sometimes, such as 22/7 for pi).
Before the fraction is displayed, it's stored in Ans in the form {denominator, numerator} (Obviously, when I displayed it, the numerator got lost).
Edit 2: changed to cover negative numbers (unfortunately, it's the denominator that becomes negative, but that can be fixed)


Last edited by Guest on 30 Jan 2005 11:12:49 am; edited 1 time in total
Back to top
BarrenSoul


Member


Joined: 22 Dec 2004
Posts: 189

Posted: 11 Feb 2005 04:17:21 pm    Post subject:

I am now an experienced user with is>( and ds<( (a whole 5 minutes practice :D) anyways I've noticed something not everone might know who's just starting to use it:

Do not do this!

DelVar B
DS<(B,1

a variable that has had DelVar [var] done to it will crash your program because it is considered undefined :)


Last edited by Guest on 11 Feb 2005 04:17:37 pm; edited 1 time in total
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 11 Feb 2005 05:33:23 pm    Post subject:

True, one of the reasons that I don't like using IS> and DS< anymore. Actually, I usually just say 0->B instead of DelVar B.
Back to top
leofox
INF student


Super Elite (Last Title)


Joined: 11 Apr 2004
Posts: 3562

Posted: 13 Feb 2005 05:42:46 am    Post subject:

I have never found a use for IS and DS... so i don't use them
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 13 Feb 2005 10:22:36 am    Post subject:

They have their uses, but they are so rare that the commands are mostly useless. I'd have preferred the 73's SetMenu( command.
Back to top
Ray Kremer


Member


Joined: 16 Feb 2004
Posts: 237

Posted: 14 Feb 2005 11:30:51 am    Post subject:

BarrenSoul wrote:
a variable that has had DelVar [var] done to it will crash your program because it is considered undefined Smile

Not to be rude, but, um, duh? Maybe I'm just used to the 86, where no variables are defined until you make them. The 83 family's method of sticking 0 in variables by default is sloppy.
Back to top
BarrenSoul


Member


Joined: 22 Dec 2004
Posts: 189

Posted: 14 Feb 2005 02:05:12 pm    Post subject:

yeah but I use the 83, and my string program can make use of ds and is but it dosn't give a decent speed boost and I have to use lbl's :)
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 14 Feb 2005 05:08:47 pm    Post subject:

why do you have to use labels? labels are bad.
Quote:
Not to be rude, but, um, duh? Maybe I'm just used to the 86, where no variables are defined until you make them. The 83 family's method of sticking 0 in variables by default is sloppy.
Sloppy but useful, sometimes.
Back to top
BarrenSoul


Member


Joined: 22 Dec 2004
Posts: 189

Posted: 14 Feb 2005 06:39:36 pm    Post subject:

sure is :)
Back to top
Ray Kremer


Member


Joined: 16 Feb 2004
Posts: 237

Posted: 15 Feb 2005 02:17:16 pm    Post subject:

Sir Robin wrote:
Sloppy but useful, sometimes.

Granted.
Back to top
axcho


Active Member


Joined: 09 Nov 2004
Posts: 555

Posted: 15 Mar 2005 12:24:05 am    Post subject:

I want to make sure this information doesn't get lost forever, since I spent quite a while writing it and it may be useful to some people.

2D Sprite Techniques in TI-83 BASIC
-------------------------------------------
Output()
--ASCII characters
--Blink characters
Text()
--ASCII characters
--Blink characters
--Textsprites
pxl-Change(), pxl-On(), pxl-Off
--Static Pixelsprites
--Variable Pixelsprites
Plot1(), Plot2(), Plot3()
--Plotsprites

So, I will start from the top.

The simplest way is to use Output() to draw an ASCII character at a specific location on the homescreen. The advantage of this is that it is fast, simple, and can be used in conjuction with a sub() command to efficiently choose a sprite to draw from a string of characters. It also can be used with strings to quickly display and scroll maps. The downside is that it is on the homescreen, and the sprites are limited to looking like ASCII characters.

A variation on this is to quickly alternate displaying between two or more characters, to combine the ASCII characters into something more interesting. This way there is an element of grayscale as well. There are, of course, many disadvantages to this, that it is on the homescreen, it is flickery, and it is slower. I have never seen this technique implemented before, but I think it could be useful in some cases.

A similar method to Output() is to use Text(), which is like Output() except on the graphscreen. This means that you can place the text on any pixel location, and the font is smaller. So both the previous methods apply here, except for the scrolling maps. Because the font size is smaller, though, your sprite selection is even more limited, and the higher resolution makes it effectively slower.

But there is a very good use for the Text() command. This is what I call Textsprites, a technique that I came upon at this topic: http://forums.unitedti.org/index.php?showtopic=2534 It involves displaying a string of characters with Text() in a For() loop. Usually the characters are drawn 1 pixel apart from left to right, so that only the first column of pixels is displayed. The columns are usually 5 pixels high, so this technique is useful for displaying 5x5 sprites. The great flexibility of this technique is that it, like all text commands, can be used in conjunction with a sub() command to easily select one sprite from a list. The main disadvantage is that it is a little slow, because it uses a For() loop. So this technique is especially useful in turn-based games, such as board games, card games, and strategy games. But the speed is not bad when compared with more flexible sprite techniques. Only when compared with plain ASCII characters does it seem slow.

Textsprites are also limited in their height of 5 pixels (though you could display larger textsprites by displaying from bottom to top as well as left to right), as well as the selection of characters. Some 5 pixel combinations are impossible using only the characters that are legal on a TI-83. They are, from top to bottom, 00101, 01011, 10110, and 11001. Others are annoying in that they take a very large horizontal space. There are two: 10100 (x root) and 11010 (squiggly x squared). Most other characters take 3 horizontal pixels and erase the 4th column of pixels. So if you want a grid of Textsprites, the most likely space you will need between each sprite is 1 blank pixel between rows, and 3 blank spaces between columns. Of course, if you manage to use only characters that are 2 pixels wide (plus 1 space) on the edges of your sprites, such as ( or [, then you can put the columns 2 pixels away instead of 3. I will put some Textsprites of mine at the end of this post.

The most common TI-BASIC sprite technique other than using ASCII characters is to use static pixelsprites. That is, using a bunch of pixel commands whose coordinates are hard-coded relative to the sprite's upper-left corner. It is pretty easy to write a program that converts an image into a string of BASIC commands that you can paste into your game. The advantage of this is that it is one of the fastest ways to get a bunch of pixels on the screen. The disadvantages have to do with flexibility. You cannot select a sprite to draw without using slow If statements, which reduces their utility in strategy games. They are probably most useful in arcade games, where there are only a few actors in the game. Usually these sprites use pxl-Change() commands so they may be erased and then drawn to a new location with the same set of instructions.

There are several ways to make displaying static pixelsprites faster. One way is to have a separate movement pixelsprite that erases part of the sprite from one end and adds to the other end to make the sprite move in one direction. You would need one of these for each direction that the sprite moves. This is only effective if the sprite moves a small number of pixels each step, though. If your graphics are tile-based, then you will have to use this next technique. The purpose of the next technique is to reduce the number pixels you have to display at a time. You do this by displaying them when the program loads, as the background. I did this in the game Treasure Hunter http://www.ticalc.org/archives/files/fileinfo/352/35242.html, which is basically a graphics demo for this method. The player and enemy sprites move on background tiles that look like grass, and they share pixels with the grass so they only have to display about half the pixels that they would normally! To design the sprites, first draw the whole sprite you want, and then pxl-Change() (otherwise known as XOR) the background tile on top of it. Then turn the resulting mush of pixels into a bunch of pixel commands that you can display on top of the background with pxl-Change() to recreate your sprite. This only works for tile-based sprites, though.

An alternative to static pixelsprites is variable pixelsprites. This trades off the speed of static pixelsprites for the greatest flexibility of all sprite techniques. Variable pixelsprites means reading data from a matrix, list, string, or other structure to determine which pixels to turn on or off. The easiest way is to just take a matrix and a couple of nested For() loops and use an If statement to see whether each matrix element is a 0 or 1, and then draw a pixel if it is a 1. However, this is both extremely inefficient and slow. Matrices store each element as an 11 byte real number, so they are overkill for a binary sprite. A much better way to do this is to use a string like in the example below. This both eliminates If statements and uses only one loop, besides taking less memory than a matrix. This example displays a random 5x5 sprite at a random location in a grid on the graphscreen. To make different sized sprites, you will have to change a few numbers in the code.

Code:
"O O OOOOOOOOO OO OOOO OOO O OO     OOO O     OO OOO    OO O   OOO   O   O OO    O O   OOOO  OOO O O O     O O   OOO   OO  O O   OOOO O O OOO  OOO O  O O   O  O OOOO O OO  OO O   OOO OOOOO   OOOOOO  O OO OO OO OO O    OOO O O
sub(Ans,1+25randInt(0,8),25\->\Str1
6randInt(0,9\->\X
6randInt(0,15\->\Y
5-10randInt(0,1\->\Z
Text(X,Y,"    
inString(Str1,"O",1
While Ans
Pxl-Change(X+iPart(.2Ans-.2),Y+iPart(.5(4-Z))+ZfPart(.2Ans-.2
inString(Str1,"O",Ans+1
End


An interesting sprite technique was introduced recently http://forums.unitedti.org/index.php?showtopic=2533. It is plotsprites, displaying a collection of points on a graph using the built-in plotting functions of the calculator. This has the advantage that it is very flexible, where you can easily edit the list of point coordinates in the middle of the program, as well as adjust the graph settings and change the style of the individual points to boxes or crosses. Here is a great example by Sir Robin of using plotsprites in a program http://forums.unitedti.org/index.php?showtopic=2542.

To use plotsprites, first set the graph window to an appropriate size, usually with one pixel per change in X or Y. Then store the X coordinates to any list, and the Y coordinates to another list. To initialize the plot, fill in the blanks in this code: PlotX(Scatter,XLIST,YLIST,\dot\ You may change the \dot\ to a \cross\ or \box\ if you want to display something other than just pixels. If you do this, you could also modify the graph settings to match the grid of a board game. There are 3 different plots you can use, which gives you only 3 sprites, unless you Augment() several lists of sprites together. To display the plotsprite, use the DispGraph command, and to change all the coordinates simultaneously, just add a single real number to the whole list of coordinates.

Here are a bunch of 5x5 textsprites that I made. I had to make compromises, especially for the chess pieces and medieval units. There are both classic and abstract chess pieces, with the white piece first, then the black.

Assuming that the sprite is stored in Ans, use this code to display them:

Code:
Ans+"  "
For(Z,1,length(Ans
Text(X,Y+Z,sub(Ans,Z,1
End


Note: Whatever is between two backslash characters is a name, not the actual character. This is how graphlink exports program files to text. For example, \cross\ is the little + character. Also, \^x\\root\ is a single token, as is \chi\\^2\ (that's what the squiggly x is called).

Code:
SMILE
"\cross\).)\cross\
FROWN
".\^2\\cross\\^2\.
WINK
":S.)\cross\
TONGUE
"-\^x\\root\e\>=\e
GRIN
"e2/2e
EVIL
"\^2\S.S\^2\
ANGRY
"):\cross\:)
SLEEP
"T\(-)\)ST
HAPPY
":)\(-)\T\(-)\
DRY
"\chi\\^2\) YT
UNSURE
" T.\^2\\cross\
COOL
"Y\chi\\^2\)YY

SPADES
"e([(e
HEARTS
"v\^2\S\^2\v
DIAMONDS
"-:):-
CLUBS
"eQ[Qe

PAWN
" s2s
" s[s
KNIGHT
"v\i\\>=\)(
"\(-)\!X[(
BISHOP
".A\^2\A.
".AQA.
ROOK
"YAYAY
"YA[AY
QUEEN
"\(-)\\box\Y\box\\(-)\
"\(-)\\box\[\box\\(-)\
KING
"eS\i\Se
"eX[Xe

P
"()))(
"([[[(
N
"\(-)\\>=\\>=\)(
"v'X[(
B
"/s)s/
"/A[A/
R
"[)))[
"[[[[[
Q
"X\>=\)\>=\X
")X[X)
K
"-:):-
"-([(-

FOOTMEN
"T:'A(
PIKEMEN
"TSeAe
KNIGHTS
"vSeQ\i\
ARCHERS
"(\xbar\\box\(.
CATAPULT
"Ae:X\^2\
CASTLE
"[v[s[
FARM
"\xbar\-\>=\)\xbar\
TREE
"\cross\([(\cross\

ROCK
"(X\>=\2(
PAPER
"[)!\>=\A
SCISSORS
"2:-:2

There are many characters that have the same first column of pixels, and usually it doesn't matter which one you use. But some are wider than others, so you will usually want to use the thinner one. For example, \(-)\ is the same as ^ but the negation sign is thinner. Also, there are sometimes tradeoffs. For example \>=\ (greater or equal to) is the same as \xbar\ but \>=\ is 1 byte and \xbar\ is 2 bytes. The problem with using \>=\ is that it is 4 pixels wide instead of 3, so if you use it at the edge, then you will get an extra column of pixels. So only use it in the middle. You will notice this above.


Here is an example to display a random playing card at the corner of the screen:

Code:
sub("e([(ev\^2\S\^2\v-:):-eQ[Qe",5randInt(1,4)-4,5)+" "+sub("A23456789TJQK",randInt(1,13),1
For(X,1,length(Ans
Text(0,X,sub(Ans,X,1
End

It doesn't have two spaces at the end to erase the end because the last character is the rank of the card!

Additional note:
Plotsprites are also good for moving lots of little guys at a time, for example, enemy ships. You do any operation on the lists of coordinates as long as the expressions resolves to a real number or a list of the same dimensions.

It can be a simple number, like gravity:
LY-1->LY

It can be a velocity that is common to all the points in the plot:
LX+U->LX
LY+V->LY

It can be a list of velocities:
{1,0,1,-1->LXVEL
{-1,0,1,1->LYVEL
...
LX+LXVEL->LX
LY+LYVEL->LY

It can be an expression that resolves to a list:
LX+(LX<X)-(LX>X->LX
LY+(LY<Y)-(LY>Y->LY

It can be a randomly generated list (slow):
LX+randInt(-1,1,4->LX
LY+randInt(-1,1,4->LY

As you can see, there are lots of possibilites, more than just the ones I've shown here. Also, you can pretty easily test to see if any of the points match up with another point:
max(X=LX and Y=LY
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 15 Mar 2005 06:53:18 pm    Post subject:

Interesting possibility with plotsprites:

Code:
"R+{0,0,1,1,2,3,3,4,4->L1
"C+{0,4,1,3,2,1,3,0,4->L2
Plot1(Scatter,L1,L2,/dot/
Repeat 0
DispGraph
Repeat Ans
getKey -> K
End
R+(K=25)-(K=34->R
C+(K=26)-(K=24->C
End

Note how just changing the values of R and C moves the plot around.
Back to top
alexrudd
pm me if you read this


Bandwidth Hog


Joined: 06 Oct 2004
Posts: 2335

Posted: 15 Mar 2005 06:57:52 pm    Post subject:

Quote:
You cannot select a sprite to draw without using slow If statements, which reduces their utility in strategy games. They are probably most useful in arcade games, where there are only a few actors in the game.

Other than that, nice job. I don't think you missed anything
Back to top
axcho


Active Member


Joined: 09 Nov 2004
Posts: 555

Posted: 15 Mar 2005 08:46:32 pm    Post subject:

Other than what? I don't understand what you are referring to. I looked and the sentences you quoted were in my post. I don't see any typos either. Do you disagree with something I said there?

I meant that having ten If statements in a row to choose a static pixelsprite in a strategy game, for example, is less efficient than choosing a textsprite with a single line of code. It is generally faster and smaller to replace If statements with functions.
Back to top
Arcane Wizard
`semi-hippie`


Super Elite (Last Title)


Joined: 02 Jun 2003
Posts: 8993

Posted: 26 Mar 2005 03:26:23 pm    Post subject:

I improved my menu routine..

"MENU TITLE,OPTION 1,OPTION 2,OPTION 3,OPTION 4,OPTION 5,OPTION 6,OPTION 7,OPTION 8,->Str0 //make sure to end the string with a ,
inString(Ans,",->X //get the length of the title
length(Str0->L //store the length of the string for later
Delvar A0->Ø //A will be a temp var for X and Ø will hold the position to draw the option at
Text(0,0,sub(Str0,1,X-1 //draw the title

While X<L //loop through all the options
X->A //remember current option offset (the "," before the current option) A+1 is the first character of the current optoin
Ans+inString(Str0,",",Ans+1->X //store the position of the next comma in X
Ø+7->Ø //next line
Text(Ans,10,sub(Str0,A+1,X-A-1 //draw option
End

7->X //starting position of the cursor
Repeat max(K={21,45,105 //untill 2nd, clear, or enter is pressed
getKey->K
If Ans:Text(X,0,"_ _ _ _ //erase the cursor if a key was pressed
X+7((Ans=34 and X<Ø)-(Ans=25 and X>7->X //move the cursor
Text(Ans,0,"> //draw the cursor
End

X/7 //return which option was chosen


Last edited by Guest on 27 Mar 2005 12:18:32 pm; edited 1 time in total
Back to top
DarkerLine
ceci n'est pas une |


Super Elite (Last Title)


Joined: 04 Nov 2003
Posts: 8328

Posted: 26 Mar 2005 07:11:07 pm    Post subject:

One small optimization:
Quote:
Ans+inString(sub(Str0,Ans+1,L-Ans),",->X
can be replaced with
Code:
Ans+inString(Str0,",",Ans+1->X

inString's optional third argument is where to start searching the string from.
Also, if you change the last part to

Code:
Repeat K=21 or K=45 or K=105 //untill 2nd, clear, or enter is pressed
getKey->K
X+7((Ans=34 and X<Ø)-(Ans=25 and X>7
If Ans!=X:Then
Text(X,0,"_ _ _
Text(Ans,0,">
Ans->X
End
End
it won't flicker when you press a wrong button.

Last edited by Guest on 27 Mar 2005 12:09:59 pm; edited 1 time in total
Back to top
Arcane Wizard
`semi-hippie`


Super Elite (Last Title)


Joined: 02 Jun 2003
Posts: 8993

Posted: 26 Mar 2005 08:06:29 pm    Post subject:

Hey, that's a cool one, fixed.

I don't really mind the flickering though, that's optional. Smile
Back to top
Display posts from previous:   
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
    » Goto page Previous  1, 2, 3 ... 8, 9, 10, 11, 12, 13  Next
» View previous topic :: View next topic  
Page 9 of 13 » All times are UTC - 5 Hours

 

Advertisement