PLAYBASIC TUTORIALS


Frame Rate Independent Animation

When writing a game, it's tempting to make an animation advance by one step every time the main loop runs.

For example, you might have something like:

Angle# = Angle# + 2.5

That works perfectly well; until the frame rate changes.

If the game is running at 60 frames per second, the animation advances 60 times every second. But if the same program drops to 30 frames per second, it only advances half as often.

The result is that the animation itself now runs at half speed.

This is where DeltaTime becomes useful.

Instead of asking:

"How many frames have passed?"

we can ask:

"How much actual time has passed?"

Once the animation is based upon elapsed time, the physical frame rate becomes largely irrelevant to its speed.




Thinking In Time

In this example, we remember the time at which the animation started:


StartTime = Timer()


Then, inside our main loop, we can calculate how much time has passed:


TimePast# = Timer() - StartTime


Timer() gives us the current time in milliseconds, so `TimePast#` represents the number of milliseconds since the animation began.

The next step is to convert that elapsed time into the equivalent number of frames.

If our ideal game frame rate is 60 FPS, then each frame represents:


1000.0 / 60.0


or approximately 16.67 milliseconds.

So we can calculate the equivalent frame number with:


Frame = TimePast# / (1000.0 / 60.0)


Now `Frame` isn't necessarily the actual number of frames the computer has rendered.

It's the number of 60 FPS frames that would have passed during that amount of time.

That's an important distinction.




Why This Works

Imagine the animation starts at exactly the same time on two different machines.

One machine manages to render the game at 60 FPS.

The other can only manage 30 FPS.

After one second, both machines have experienced approximately 1000 milliseconds of real time.

Our calculation therefore produces approximately:


1000 / 16.67 = 60 frames


for both machines.

The 60 FPS machine may have actually rendered around 60 frames.

The 30 FPS machine may have only rendered around 30.

But both animations have progressed by the same amount because the animation is being driven by elapsed time, not by the number of times the main loop happened to execute.

This gives us a simple way of separating the speed of an animation from the frame rate used to display it.




Applying It To The Animation

Once we have our virtual frame number, we can use it anywhere we would normally use a frame counter.

In this example, the animation changes the radius of a circle:

PlayBASIC Code:
Speed# = 2.5

Angle# = WrapAngle(Frame * Speed#)

Radius# = 50 + Sin(Angle#) * 40
COMMANDS USED: WRAPANGLE | SIN |


The angle is effectively saying:

"At this point in time, where would this animation be if it were running at our ideal 60 FPS?"

We can then use that angle to calculate the current radius of the circle.

The actual object could just as easily be a sprite, character, camera, particle, UI element, colour value, or pretty much anything else that changes over time.




The Complete Example

Here's the complete PlayBASIC example:

PlayBASIC Code:
; Remember the time this loop started as were going to 
; use it to compute delta time during the main loop
StartTime =timer()

; Main loop
do

    ;  Clear screen to black (default rgb colour)
    cls    

    ; Elapsed time - start of current frame
    TimePast#=Timer()-Starttime

    ; Convert the Time past into frame index (at a frame rate of 60fps))
    Frame = TimePast# /(1000.0/60.0)

    ; Animation speed (degrees changed per frame)
    Speed# = 2.5

    ; Compute the animation angle 
    ;    frame * speed wraped back into 0-359 degrees
    Angle# = Wrapangle(Frame * Speed#)    

    ; Use animation angle to compute radius of circle
    Radius# =  50+sin(Angle#)*40

    ; draw a circle in the center of screen of default screen
    ; at the current size this frame.
    circle 400,300,Radius#,true

    ; show the newly drawn frame to the user
    sync

; loop back until the user hits the space bar
loop spacekey()
COMMANDS USED: TIMER | CLS | WRAPANGLE | SIN | CIRCLE | SYNC | SPACEKEY |






It Doesn't Have To Be 60 FPS

There's nothing particularly special about 60 FPS here.

We're simply using 60 FPS as our reference frame rate.

You could instead define it as:


GAME_FRAME_RATE = 30


or:


GAME_FRAME_RATE = 120


and calculate the duration of an ideal frame from that.

The important thing is that the animation has a consistent relationship with time, rather than depending upon how quickly the main loop happens to execute.




A Small Change With A Big Benefit

This is one of those techniques that can seem unnecessarily complicated when you're first writing a game.

If your program always runs at 60 FPS, simply advancing an animation every frame appears to work perfectly well.

But as soon as frame rates become variable, the difference becomes obvious.

By introducing elapsed time into the equation, we can make our animations behave consistently across different machines and different frame rates.

The computer is still drawing frames as quickly as it can.

We're simply no longer allowing the number of frames it draws to dictate how fast time appears to pass inside our game.


PlayBASIC Tutorial: Intro To Functions (UPDATE)

PlayBASIC Tutorial: Intro To Functions - (2018-07-06)

Hi welcome to our Intro to Functions tutorial.  In this tutorial we start out with some revision of Gosub / Return statements, which are used to create a simple sub routine.  Sub routines are changes in  program flow,  allowing the programmer to execute a chunk of code that's external to the section they may be writing, then upon completion the control returns to the caller.    This is the same basic model that functions introduction to our programming, except functions are more formalized.  Meaning they have some strict rules about syntax and intro a new concepts such as scope changes, which sub routines don't have. 
   
  The types of functions shown in video are very simple, initially we start by taking a sub routine that prints rows of text and convert that to function.  Through this process we encounter our first problem which is variable scope and look at ways to solve it, such as making our variable global, or better yet passing a variable into the function as a parameter .  Later in the video, we create our own custom distance function, as well building a function that does some simple string manipulation   

  NOTE: This video was  recorded alive with only a few changes for length..


Video:(Updated Audio)


Old Video:



Example Code:

PlayBASIC Code:
            print ProcessString( "-------Hello World-------")
            print ProcessString( "    1234    " )
            

            Dist# = CustomDistance( 100,100,700,300)
            
            print dist#


            for lp =0 to 10
                    Print_Lines_function( lp )            
            next
            print "--------------------------------------------------"
            
            sync
            waitkey
  
            end      
      



function Print_Lines_function( LoopCounter )
            print "--------------------------------------------------"
            print "Loop Counter="+str$(LoopCounter)
endfunction 

          
          
Function CustomDistance( X1#,Y1# , X2#,Y2#)
    
            DX# = abs(X1#-X2#)
            DY# = abs(Y1#-Y2#)
            
            DistResult# = sqrt( DX# * DX# + Dy# * DY#)    
    
EndFunction DistResult#

            
            
Function ProcessString( MyString$)    

            MyString$ = trim$(MyString$,"-")

            MyString$ = Replace$( MyString$," ","~" )

EndFunction MyString$
COMMANDS USED: PRINT | SYNC | WAITKEY | STR$ | ABS | SQRT | TRIM$ | REPLACE$ |



Common Variables Questions In PlayBasic







Learn To Code: Introduction To Variables (Integers / Floats & Strings) in PlayBASIC




Q) Whats the numeric range of a 32bit integer



A) The numeric range of a 32-bit integer is -2147483648 to 2147483647.

In a 32-bit signed integer, one bit is used to represent the sign of the number (positive or negative), and the remaining 31 bits are used to represent the magnitude of the number. This means that a 32-bit integer can represent any integer value in the range -2147483648 to 2147483647, inclusive.

Here's a breakdown of the range of values that can be represented by a 32-bit integer:

- The largest positive number that can be represented is 2147483647. This is the value that is obtained when all 31 magnitude bits are set to 1 and the sign bit is set to 0.

- The smallest negative number that can be represented is -2147483648. This is the value that is obtained when all 31 magnitude bits are set to 1 and the sign bit is set to 1.

- The range of values between -2147483648 and 2147483647 includes all possible integer values that can be represented using a 32-bit signed integer.



Q) How do add or subtract 32bit integers together ?

To add or subtract 32-bit integers, you can use the standard arithmetic operators + and - in your code.

For example, to add two 32-bit integers x and y, you can use the following code:

PlayBASIC Code:
 z = x + y
COMMANDS USED:


To subtract y from x, you can use the following code:

PlayBASIC Code:
 z = x - y
COMMANDS USED:


Both of these operations will work regardless of the size of the integers, as long as the result fits within the range of values that can be represented by a 32-bit integer.

In most programming languages, 32-bit integers have a range of -2147483648 to 2147483647. This means that the result of an addition or subtraction operation must be within this range in order to be stored in a 32-bit integer.

If the result of the operation is outside of this range, the result may be truncated or wrapped around to fit within the range. This can cause unexpected results, so it is important to check the range of the result before storing it in a 32-bit integer.

In summary, you can use the + and - operators to add and subtract 32-bit integers, and you should check the range of the result to ensure that it fits within the range of values that can be represented by a 32-bit integer.



Q) How can I multiply or divide 32 bit integer variables


To multiply or divide 32-bit integer variables, you can use the standard arithmetic operators * and / in your code.

For example, to multiply two 32-bit integers x and y, you can use the following code:

PlayBASIC Code:
 z = x * y
COMMANDS USED:


To divide x by y, you can use the following code:

PlayBASIC Code:
 z = x / y
COMMANDS USED:


Both of these operations will work regardless of the size of the integers, as long as the result fits within the range of values that can be represented by a 32-bit integer.

In most programming languages, 32-bit integers have a range of -2147483648 to 2147483647. This means that the result of a multiplication or division operation must be within this range in order to be stored in a 32-bit integer.

If the result of the operation is outside of this range, the result may be truncated or wrapped around to fit within the range. This can cause unexpected results, so it is important to check the range of the result before storing it in a 32-bit integer.

In summary, you can use the * and / operators to multiply and divide 32-bit integers, and you should check the range of the result to ensure that it fits within the range of values that can be represented by a 32-bit integer.




Q) What's the numeric range of a 32bit float ?

The numeric range of a 32-bit float, also known as a single-precision floating-point number, is approximately 3.4 x 10^-38 to 3.4 x 10^38.

In a single-precision floating-point number, the range of values that can be represented is determined by the number of bits used for the significant (mantissa) and the exponent. In a 32-bit float, 23 bits are used for the significant and 8 bits are used for the exponent.

The smallest positive number that can be represented in a 32-bit float is approximately 1.4 x 10^-45, and the largest positive number is approximately 3.4 x 10^38. The range of values between these two numbers includes all possible positive single-precision floating-point numbers.

Negative numbers are also possible, and the range of negative values is the same as the range of positive values, but with the opposite sign. This means that the smallest negative number that can be represented in a 32-bit float is approximately -3.4 x 10^38, and the largest negative number is approximately -1.4 x 10^-45.

The range of values that can be represented using a 32-bit float is not an exact range, but rather an approximate range, because the values are represented using a finite number of bits. The precision of the values within this range may also vary depending on the exponent.




Q) When would I choose to use 32bit integer instead of a 32bit float ?


You would choose to use a 32-bit integer instead of a 32-bit float (single-precision floating-point number) when you need to represent integer values and do not need a fractional component.

Integer values are whole numbers that do not have a fractional component, such as 1, 2, 3, 4, etc. Integer values can be positive, negative, or zero.

On the other hand, floating-point numbers are numbers that have a fractional component, such as 1.5, 2.6, 3.14, etc. They can also be positive, negative, or zero.

There are a few reasons why you might choose to use a 32-bit integer instead of a 32-bit float:

Integer values take up less space in memory than floating-point numbers. A 32-bit integer uses 4 bytes of memory, while a 32-bit float uses 4 bytes of memory.

Integer values are faster to process than floating-point numbers. This is because most computers have special hardware that is optimized for processing integer values, and integer operations are generally faster than floating-point operations.

If you need to represent a value that does not have a fractional component, using a floating-point number would be unnecessary and could introduce additional complexity or error.

In general, you should use a 32-bit integer when you need to represent integer values and do not need a fractional component, and use a 32-bit float when you need to represent decimal values and need a fractional component.



Q). Can i perform addition subtracts multiplication or division between 32bit integers and 32bit floats ?


Yes, you can perform arithmetic operations between 32-bit integers and 32-bit floats (single-precision floating-point numbers) in most programming languages.

When you perform arithmetic operations between integers and floats, the result will be a float. For example:

PlayBASIC Code:
  x = 5 // 32-bit integer
  y# = 2.5 // 32-bit float

  z# = x + y# // z is a float (7.5)
  w# = x * y# // w is a float (12.5)
COMMANDS USED:


You can also mix and match arithmetic operations between integers and floats. For example:

PlayBASIC Code:
  x = 5 // 32-bit integer
  y# = 2.5 // 32-bit float

   z# = x + y# * 2 // z is a float (10)
   w# = (x + y#) / 2 // w is a float (3.75)
COMMANDS USED:


When you perform arithmetic operations between integers and floats, it is important to be aware of the potential for loss of precision, particularly when you are working with large or small numbers. Floating-point numbers have a fixed number of bits to represent the significant (mantissa) and the exponent, which means that they can only represent a finite set of values. This can cause some values to be rounded or approximated when they are represented as floats.

In summary, you can perform arithmetic operations between 32-bit integers



Q)How DO I compare numeric variables together ?


To compare numeric variables, you can use the comparison operators > (greater than), < (less than), >= (greater than or equal to), <= (less than or equal to), = (equal to), and <> != (not equal to).

For example, to compare two variables x and y to see if x is greater than y, you can use the following code:

PlayBASIC Code:
if (x > y) 
 // Do something
endif
COMMANDS USED:


To see if x is less than or equal to y, you can use the following code:

PlayBASIC Code:
if (x <= y) 
 // Do something
endif
COMMANDS USED:


To see if x is equal to y, you can use the following code:

PlayBASIC Code:
if (x = y)
 // Do something
endif
COMMANDS USED:


To see if x is not equal to y, you can use the following code:

PlayBASIC Code:
if (x <> y) 
 // Do something when there not equals
endif


if (x != y) 
 // Do something when there not equals
endif
COMMANDS USED:


These operators work with any numeric data type, including integers, floats, and doubles.

It's important to note that the comparison between different data types can produce rounding or truncating errors. So it's best to convert your variable to the same datatype when making comparisons between them.




Q) What's can a String variable hold ?


A string variable is a variable that holds a sequence of characters.

In most programming languages, a string is a data type that represents a sequence of characters, such as a word, a sentence, or a series of words and sentences. Strings are often used to store and manipulate text data, such as in a database or a document.

Strings can be stored in variables just like other data types, such as numbers or booleans. For example, in the following code snippet, the variable message$ is a string that holds the value "Hello, World!"

PlayBASIC Code:
  message$ = "Hello, World!"
COMMANDS USED:


You can manipulate strings by concatenating them, extracting substrings, and performing other operations on them. For example, you can concatenate two strings using the + operator, like this:

PlayBASIC Code:
 greeting$ = "Hello, "
 name$ = "John"
 fullGreeting$ = greeting$ + name$ // "Hello, John"
COMMANDS USED:



You can also use string functions and methods to manipulate strings. For example, you can use the length property to get the length of a string, or the mid$() function to extract a substring from a larger string.

PlayBASIC Code:
 message$ = "Hello, World!"
 messageLength = len(message$) // 13
 firstWord$ = mid$(message,1, 5) // "Hello"
COMMANDS USED: LEN | MID$ |


In summary, a string variable is a variable that holds a sequence of characters, and you can manipulate strings by concatenating them, extracting substrings, and using various string functions and methods.



Q) When would I choose to use a String variable instead of a 32bit Integer or 32bit float ?

A) You would choose to use a string variable instead of a 32-bit integer or 32-bit float when you need to represent and manipulate text data, rather than numeric data.

Integer variables are used to represent whole numbers that do not have a fractional component, such as 1, 2, 3, 4, etc. Integer variables are useful for representing and manipulating numerical data, such as counts, quantities, and other values that do not have a decimal component.

Floating-point variables, also known as single-precision floating-point variables, are used to represent decimal values that have a fractional component, such as 1.5, 2.6, 3.14, etc. Floating-point variables are useful for representing and manipulating decimal values, such as measurements, coordinates, and other values that require a fractional component.

On the other hand, string variables are used to represent and manipulate text data, such as words, sentences, and other sequences of characters. String variables are useful for representing and manipulating text data, such as names, addresses, and other values that are expressed as text.

In general, you should use a string variable when you need to represent and manipulate text data, and use an integer or floating-point variable when you need to represent and manipulate numeric data.

For example, you might use a string variable to store a person's name, and use an integer variable to store their age. Or, you might use a string variable to store a product's description, and use a floating-point variable to store its price.



Q) How do I append strings together ?


To append two strings together, you can use the concatenation operator + or the concatenation assignment operator +=.

For example, to append two strings s1 and s2 together and store the result in a new string s3, you can use the following code:

s3$ = s1$ + s2$


To append s2 to the end of s1, you can use the following code:

s1$ += s2$

Both of these operations will work regardless of the size of the strings or the data they contain.

In most programming languages, strings are immutable, which means that they cannot be modified once they have been created. When you perform a concatenation operation, the original strings are not modified; instead, a new string is created that contains the concatenated result.

You can also use string interpolation to append strings together. String interpolation allows you to embed expressions inside a string literal, and the expression is evaluated and the result is included in the string.

For example, you can use string interpolation to append a string and a variable together like this:

name$ = "John";
greeting$ = "Hello, " +name$ +"!" // "Hello, John!"

In summary, you can use the + and += operators to append two strings together, and you can use string interpolation to embed expressions in a string and append them together.





Q) What characters can a string variable hold ?


A string variable can hold any sequence of characters that is allowed by the encoding used to represent the string.

In most programming languages (such as PlayBASIC), strings are stored as sequences of bytes, and each character in the string is represented by one or more bytes, depending on the character encoding that is used.

The most common character encoding for strings is ASCII (American Standard Code for Information Interchange), which uses a single byte to represent each character. ASCII includes 128 characters, including the upper and lowercase letters of the English alphabet, digits 0 through 9, punctuation marks, and a few special characters such as the dollar sign ($) and the at symbol (@).

Other character encodings, such as Unicode, can represent a much larger set of characters, including characters from many different scripts and languages. Unicode uses a variable-length encoding scheme, which means that each character can be represented by one or more bytes, depending on the character. Unicode includes over 100,000 characters, covering virtually every written language in the world.

In summary, a string variable can hold any sequence of characters that is allowed by the character encoding that is used to represent the string. ASCII and Unicode are the most common character encodings for strings, and both of these encodings support a wide range of characters.



Q.) What's the difference between a bit and a byte ?

A bit is the smallest unit of data in a computer, and a byte is a group of bits that is used to represent a character or a small integer.

A bit is a binary digit, which can have one of two values: 0 or 1. Bits are used to represent the values of variables and to store data in a computer's memory.

A byte is a group of 8 bits that is used to represent a character or a small integer. A byte can represent any of 256 different values, because 2 to the power of 8 (2^8) is equal to 256.

Here are some examples of the relationship between bits and bytes:

A single bit can represent a boolean value (true or false).

A group of 4 bits is known as a nibble, and can represent a small integer value between 0 and 15.

A byte can represent a single character in the ASCII character set, which includes upper and lowercase letters, digits, punctuation marks, and a few special characters.

A byte can also represent a small integer value, such as a number between 0 and 255.

In summary, a bit is the smallest unit of data in a computer, and a byte is a group of 8 bits that is used to represent a character or a small integer. Bytes are used to store data in a computer's memory, and are the basic unit of storage for most computer systems.



Q) How would I extract bits from an 32bit integer into separate variables


To extract bits from a 32-bit integer and store them in separate variables, you can use bit shifting and masking operations.

Bit shifting is the process of moving the bits in a binary number to the left or right by a certain number of positions. Bit masking is the process of isolating specific bits from a binary number by applying a mask to the number.

Here's an example of how you might extract the bits from a 32-bit integer and store them in separate variables using bit shifting and masking:

PlayBASIC Code:
  num = 123456; // 32-bit integer

// Extract the upper 16 bits and store them in a 16-bit integer
  upperBits = num >> 16;

// Extract the lower 16 bits and store them in a 16-bit integer
lowerBits = num & 0xffff;

// Extract the 8 bits at positions 8 through 15 and store them in an 8-bit integer
 middleBits = (num >> 8) & 0xff;


print bin$(num)
print bin$(lowerBits)
print bin$(middleBits)

sync
waitkey
COMMANDS USED: PRINT | BIN$ | SYNC | WAITKEY |




In this example, the >> operator is used to shift the bits of the integer to the right by the specified number of positions. The & operator is used to apply a mask to the integer, which allows you to isolate specific bits.

You can use these techniques to extract any subset of bits from a 32-bit integer and store them in separate variables. You can also use bit shifting and masking to extract bits from integers of other sizes, such as 8-bit, 16-bit, and 64-bit integers.

In summary, you can use bit shifting and masking operations to extract specific bits from a 32-bit integer and store them in separate variables. These operations allow you to manipulate the bits of an integer and extract the specific data that you need.



Repeat / Until and While / EndWhile Control Loops In PlayBasic



REPEAT UNTIL LOOPS in PlayBASIC


In PlayBASIC, the Repeat/Until control structure allows you to repeatedly execute a block of code until a certain condition is met. The syntax for the Repeat/Until structure is as follows:


Repeat
' code to be executed repeatedly
Until condition



The code block between Repeat and Until will be executed repeatedly until the condition is met. When the condition is met, the loop will exit and control will be passed to the next line of code after the Until statement.

Here is an example of a Repeat/Until loop in PlayBASIC:

PlayBASIC Code:
x = 0

Repeat
  x = x + 1
  Print x
Until x = 10

Print "Loop complete"
sync
waitkey
COMMANDS USED: PRINT | SYNC | WAITKEY |


In this example, the loop will repeat 10 times, printing the value of x each time. When x reaches 10, the Until condition will be met and the loop will exit. The message "Loop complete" will then be printed.


Read PlayBASIC Help Files about LOOPS


While / EndWhile Control Structures In PlayBASIC


In PlayBASIC, the While/EndWhile control structure allows you to repeatedly execute a block of code as long as a certain condition is met. The syntax for the While/EndWhile structure is as follows:


While condition
' code to be executed repeatedly
EndWhile


The code block between While and EndWhile will be executed repeatedly as long as the condition is met. When the condition is no longer met, the loop will exit and control will be passed to the next line of code after the EndWhile statement.

Here is an example of a While/EndWhile loop in PlayBASIC:

PlayBASIC Code:
x = 0

While x < 10
  x = x + 1
  Print x
EndWhile

Print "Loop complete"
sync
waitkey
COMMANDS USED: PRINT | SYNC | WAITKEY |


In this example, the loop will repeat until x is no longer less than 10. The loop will print the value of x each time it is executed, and when x reaches 10 the While condition will no longer be met and the loop will exit. The message "Loop complete" will then be printed.


Read PlayBASIC Help Files about LOOPS






Can you explain what the DO / LOOP control structure is in PlayBasic ?


Can you explain what the DO / LOOP control structure is in PlayBASIC ?


In PlayBASIC, the DO/LOOP control structure allows you to repeatedly execute a block of code a specific number of times or until a certain condition is met. There are two forms of the DO/LOOP structure: the DO/LOOP form and the DO/LOOP WHILE form.

The DO/LOOP form has the following syntax:

DO
' code to be executed repeatedly
LOOP


The code block between DO and LOOP will be executed repeatedly until the EXIT DO statement is encountered.

Here is an example of a DO/LOOP loop in PlayBASIC:

PlayBASIC Code:
x = 0

DO
  x = x + 1
  Print x
  If x = 10 Then ExitDO
LOOP

Print "Loop complete"
sync
waitkey
COMMANDS USED: PRINT | SYNC | WAITKEY |


In this example, the loop will repeat 10 times, printing the value of x each time. When x reaches 10, the Exit DO statement will be encountered and the loop will exit. The message "Loop complete" will then be printed.

The DO/LOOP WHILE form has the following syntax:


DO
' code to be executed repeatedly
LOOP Optional While condition


The code block between DO and LOOP will be executed repeatedly as long as the condition is met. When the condition is no longer met, the loop will exit and control will be passed to the next line of code after the LOOP statement.

Here is an example of a DO/LOOP WHILE loop in PlayBASIC:

PlayBASIC Code:
x = 0

DO
  x = x + 1
  Print x
LOOP x < 10

Print "Loop complete"
COMMANDS USED: PRINT |


In this example, the loop will repeat until x is no longer less than 10. The loop will print the value of x each time it is executed, and when x reaches 10 the LOOP WHILE condition will no longer be met and the loop will exit. The message "Loop complete" will then be printed.

So, in general, you might use a DO/LOOP loop when you want to repeat a block of code an unknown number of times, or when you want to repeat a block of code until a certain condition is met. On the other hand, you might use a DO/LOOP WHILE loop when you want to repeat a block of code a specific number of times, or when you want to repeat a block of code while a certain condition is true.