QuickFire 2.1
Copyright Ó 2003 Visualisation Systems
LtdQuickFire has been released as Trialware. You are free to use and distribute the software as originally packaged by Visualisation Systems Ltd providing that no payment is made or received. Under no circumstances are you to distribute any personalised license key you obtain as a registered user.
The Trial version allows you to develop QuickFire applications on either a standalone computer or remotely using a Java Enabled Internet Browser over the Internet. Registering QuickFire will unlock the QuickFire compiler enabling you to make standalone applets that can be embedded on your web pages. You can register QuickFire and obtain a license by visiting:-
http://www.visualisationsystems.co.uk/QuickFire/Home.jsp
Preface
*Introduction
*Installation
*Obtaining the Distribution
*Unzipping the Distribution
*Contact Details
*Registration and obtaining a license
*Lost licenses
*Email Support
*Forums
*Starting QuickFire
*Starting QuickFire on your Local Machine
*Starting QuickFire remotely using an Internet Browser
*Command Line Access
*Command Line Configuration
*DOS / Windows 95 / Windows 98 / Windows XP Configuration
*Linux / Unix Configuration
*Testing the command line interpreter (All Versions)
*Testing the command line compiler (Registered Version Only)
*Command Line Commands
*qfe - QuickFireEditor
*qfi QuickFireInterpreter
*qfc QuickFire Compiler
*qfr QuickFire Run Command
*vdm Virtual Disk Manager
*Security Online Access
*Automatic Security Configuration for Apache using apache.setup script
*Manual Security Configuration for Apache
*Adding New Users
*License
*QuickFire Language Syntax
*Conventions
*The Hello World Program
*Commenting your programs
*Data Types
*Constants
*Variables and Variable Declaration
*Cast Operators
*Coercion
*Basic Arithmetic
*Parenthesis Operator
*Pre/Post Increment Operator
*Pre/Post Decrement Operator
*Relation expressions and operators
*Control flow
*Looping
*Bitwise Operators
*Logical Operators
*Combined Assignment operators
*Functions and Function calls
*Arrays
*Pass by Value and Pass by Reference
*Operator Precedence
*Run Time Library Functions
*String functions (Core)
*charstr()
*midstr()
*leftstr()
*rightstr()
*strlen()
*strpos()
*File I/O functions (Applet)
*open()
*create()
*close()
*eof()
*readByte()
*readShort()
*readInt()
*readLong()
*readFloat()
*readDouble()
*readString()
*writeByte()
*writeShort()
*writeInt()
*writeLong()
*writeFloat()
*writeDouble()
*writeString()
*Mathematical functions
*sin() - Sine (Radians)
*asin() - Arc-Sine (Radians)
*cos() - Cosine (Radians)
*acos() - Arc-Cosine (Radians)
*tan() - Tangent (Radians)
*atan() - Arc-Tangent (Radians)
*sind() - Sine (Degrees)
*asind() Arc-Sine (Degrees)
*cosd() Cosine (Degrees)
*acosd() Arc-Cosine (Degrees)
*tand() Tangent (Degrees)
*atand() Arc-Tangent (Degrees)
*sqrt() Square Root
*log() Natural Logarithm
*exp() Computes ex
*log10() Logarithm in Base 10
*pow() Computes xy
*random() Returns random number between 0.0 and 1.0 inclusive
*Throttle Functions
*ThrottleSet()
*ThrottleTime()
*Sleep()
*Yeild()
*Bit Manipulation Functions
*ffbs() find first bit set
*ffbc() find first bit clear
*Display Functions
*Refresh()
*print()
*DisplayWidth()
*DisplayHeight()
*Mouse Functions
*MouseX()
*MouseY()
*MouseButton()
*Keyboard Functions
*Getchar()
*Inkey()
*Sprite Functions
*SpriteCollision()
*SpriteClearArea()
*SpriteCopyArea()
*SpriteCount()
*SpriteCreate()
*SpriteDrawTo()
*SpriteFillArea()
*SpriteFrameCount()
*SpriteGetHeight()
*SpriteGetPixelAt()
*SpriteGetWidth()
*SpriteLoad()
*SpriteMerge()
*SpriteMove()
*SpritePlot()
*SpritePolyBegin()
*SpritePolyDrawTo()
*SpritePolyEnd()
*SpritePrintCenter()
*SpritePrintLeft()
*SpritePrintRight()
*SpriteRotate()
*SpriteScale()
*SpriteSelectFrame()
*SpriteSetColour()
*Audio Functions
*AudioLoad()
*AudioPlay()
*AudioStart()
*AudioStop()
*AudioStopAll()
*
QuickFire is an online program development environment, which is strongly influenced by the "C" programming language. Although QuickFire compiles to Java class files (Registered version only) it is a much smaller language and hence easier to learn.
QuickFire may even be a good introduction to programming if you have never programmed before. It takes care of many of the problems that beginners to more complex languages (like Java) encounter. QuickFire's runtime library concentrates more on what you want to do, rather than setting up and instantiating a complex class hierarchy to do a simple task.
QuickFire Applets, once compiled, can be quickly, and easily, integrated with your Internet Webpages. In fact they can be used wherever a Java Applet can be used.
What do we mean by an online program development environment? Put simply, the development environment works within an Internet Browser and uses Internet Servers to store your programs and data files. This means that you can access your QuickFire environment, programs and data files whenever you have access to a computer equipped with a compatible Java enabled Internet Browser (Internet Explorer, Netscape etc). The QuickFire environment can even be accessed through a corporate Firewall, which enables you to develop your programs during work lunchtime and breaks.
You may think that QuickFire, being Internet Centric, would take a long time to download, however, you will find that the development environment is quite compact. At ~120K it only take around 20 seconds to load on a 56K/bit dialup connection. Once loaded, QuickFire runs completely within the browser and only connects to the server to load and save your files. It's even Quicker using QuickFire's Virtual Disk images since your files are loaded and saved to a Virtual Disk held in the memory of your browser. There is then no Internet communication or Network traffic whatsoever, until you want to save the virtual disk to the server.
The QuickFire distribution contains the software necessary to use a server of your choice providing that it supports PHP4. The supplied server side software supports multiple users using the security features inherent on most Internet Browsers. If you don't have access to a suitable server then registration gives you access to our pre-configured server including 10MB of storage.
QuickFire features up to 64 foreground sprites and a background sprite. Sprites are independently moveable graphics objects that overlays the main display. Sprites can be rotated through a full 360 degrees. Sprite can also be scaled in both width and height thus making it easy to enlarge, shrink or flip objects. QuickFire automatically checks for collisions between sprites you can detect if any sprite overlaps any other sprite. Collision detection can be enabled or disabled for each pixel within the sprite. Sprites can also have transparent pixels allowing background object to show through. Sprite can also contain a sequence of images allowing animation to be performed.
QuickFire has been released as Trialware and you are free to use and distribute the software as originally packaged. The Trial version allows you to develop QuickFire applications directly within your Internet Browser using the QuickFire Interpreter. Under no circumstances are you to distribute any personalised license key you obtain as a registered user.
If you find the software useful then please consider registering on our website:-
http://www.visualisationsystems.co.uk/QuickFire/Home.jsp
Registration unlocks the additional features and gives you the following benefits:-
There are several steps involved in installing QuickFire on your system.
Since you're reading this document its a fair assumption that you've already obtained a copy of the distribution. However, before proceeding any further, you should check to see if there is a later release available. You can check this by visiting the Downloads section at:-
http://www.visualisationsystems.co.uk/QuickFire/Home.jsp
You should now unzip the distribution into a suitable directory. If you are intending on accessing the system over the Internet then you should unzip it directly into a directory on your web server.
Registration and obtaining a license
You can register your copy of QuickFire and obtain a license unlocking the QuickFire compiler by visiting http://www.visualisationsystems.co.uk/
You can download a fresh license file from our server at anytime during your period of registration. If you cannot remember your username or password then please Email <support@visualisationsystems.co.uk> for further instructions.
Email support is available to licensed users of QuickFire. Email queries should be sent to <support@visualisationsystems.co.uk> stating your registered username.
QuickFire self-help support can also be obtained by posting messages in our forums accessible at:- <http://www.visualisationsystems.co.uk/forums/index.php>.
Starting QuickFire on your Local Machine
To start QuickFire on most computers all that is necessary is to double click QuickFireFull.jar in the QuickFire installation directory. If QuickFire doesn't start then you will have to set up the command line utilities and start the editor using the "qfe" command.
If you are running an unlicensed version of QuickFire then the program will give you a chance to locate the license file. Don't worry if you haven't got a license since you can continue your QuickFire session in evaluation mode. If you decide that QuickFire is useful then please consider obtaining a license by registering at:-
http://www.visualisationsystems.co.uk/QuickFire/Home.jsp
Starting QuickFire remotely using an Internet Browser
In order to test QuickFire's online access features you must have installed QuickFire into a directory on your Internet Web Server that is accessible via a standard URL.
You must also be running a web server supporting PHP4. We may consider supporting other formats if there is sufficient demand (CGI/JSP/Servlets etc). Our own QuickFire server is based around Java Servlets but this is not included in this distribution.
Assuming that you meet these requirements you should simply direct your browser to the URL where "editor.php" is installed.
For example, If you installed QuickFire into "/QuickFireApp" on www.yourserver.com then QuickFire could be accessed using the following URL:-
http://www.yourserver.com/QuickFireApp/editor.php
You should be presented with a simple web page with a file selector containing "examples.qfd".
Select "examples.qfd" and press the "Load" button.
After a short pause, while the QuickFire environment is downloads, the QuickFire editor should popup in its own frame and a new web page containing a blank applet should appear in the Browser.
Select "Load" from the "File" menu. You should be presented with a file selector. Select "SpriteDemo.qf" and press "Load" on the file selector. You should find that a small program is displayed in the editor. To start the program select the "Run" item from the "Run" menu. The program should now have started. To stop the program select the "Stop" menu item immediately below the "Run".
The next thing to check is that the Virtual Disk can be written back to the server. To do this simply press the "Save Virtual Disk" button.
If you get a "Error" Dialog with the message "Failed to save Virtual Disk Read Only Image / Server Down / Bad Poster URL" then your system has not been configured correctly. Lets take each of these in turn:-
cd QuickFireApp
cd guest
chmod 777 examples.qfd
Once you've got this far you have a working QuickFire system that can be accessed over the Internet. The default installation only provides a guest area and there is nothing to prevent anyone using your QuickFire installation and images. Whilst this is OK during installation, you would probably want to have some form of security to prevent unauthorised access. The PHP script "editor.php" is set up to use the Basic Security features available in modern browsers. More information can be found in the chapter on Security and Online Access.
Additional configuration is necessary to use the command line utilities. This is slightly different depending on what type of machine you are using but it basically comes down to adding the appropriate directory containing the commands to the system path. A configuration file also needs to be edited for the Windows command line.
DOS / Windows 95 / Windows 98 / Windows XP Configuration
Notes:
There are two steps you need to perform in order to run QuickFire under DOS / Windows 95 / Windows 98 or Windows XP. Firstly, before starting QuickFire for the first time, you need to create a "qfconfig.bat" file and secondly you need to add QuickFire to your path.
The "qfconfig.bat" should be created in QuickFireApp\dos (or winxp) directory. Its simply a copy of "qfconfig.orig" with a two lines modified to suit your system configuration.
cd QuickFireApp\dos
copy qfconfig.orig qfconfig.bat
You now need to edit "qfconfig.bat". Near the top of "qfconfig.bat" you will find two lines similar to:-
set QUICKFIREDIR=c:\QuickFireApp
set JAVADIR=c:\windows\system32
In the case of QUICKFIREDIR simply replace the text following the "=" with the absolute directory path to your QuickFire installation. The absolute directory path is the full path starting with the drive letter, for example, "c:\", "d:\" etc.
You now need to update JAVADIR to point to the directory containing "java.exe". The initial directory may be OK depending on you system. If you have problems then you can find "java.exe" from the command line by entering the following command:-
dir/s c:\java.exe
If you find several copies then you may have to try each of them in turn.
You now need to add QuickFireApp\dos (or winxp) to your path. This can be done from the command line by typing the following command:-
set PATH=C:\QuickFireApp\dos;%PATH%
or in the case of Windows XP
set PATH=C:\QuickFireApp\winxp;%PATH%
If you've installed QuickFire elsewhere then you will need to adjust the path appropriately.
Typing the command at the command line must be done each time you restart the system so you will probably find it more convenient to add the command to your autoexec.bat file or some other small batch file.
There are three things that need to be done to run QuickFire under a Linux or UNIX system:-
export PATH
PATH=$HOME/QuickFireApp/bin:$PATH
This should be placed in your shells start up file. E.g. ".profile", ".bashrc" etc.
export CLASSPATH
CLASSPATH=$HOME/QuickFireApp:.:$CLASSPATH
CLASSPATH=$HOME/QuickFireApp/*.jar:$CLASSPATH
find / -name "java" print
Common locations are:-
/usr/bin/java and /usr/local/bin/java
Testing the command line interpreter (All Versions)
Change into the "examples" subdirectory under "QuickFireApp".
Now run the Interpreter using the following command:-
qfi HelloWorld.qf
If the interpreter respond with: "Hello, World!" then it is running correctly. If it didn't respond with "Hello World" then double check the command line configuration paying particular attention to paths and drive specifiers.
Testing the command line compiler (Registered Version Only)
Change into the "examples" subdirectory under "QuickFireApp".
Now run the Compiler using the following command:-
qfc standard HelloWorld.qf
QuickFire is issued as Trialware and access to the compiler is limited to registered users. If you are in possession of a license issued to yourself and the compiler responds with "License not installed or not valid" then you have not yet installed the license. The license should be installed within the QuickFire editor which can be started by double clicking on "QuickFireFull.jar" or typing "qfe" on the command line.
Assuming that you had correctly installed license you should now find that you have a "HelloWorld.class" file in your current directory. You can run this program from the command line by typing the following command:-
qfr HelloWorld
The program should respond with: "Hello, World!"
Usage: qfe
This command starts the standalone QuickFire editor. This should be used if you are writing QuickFire program locally.
Usage: qfi [-standard] [-applet] filename
This command is used to interpret a QuickFire program designed for the command line "-standard". Although the command has a "-applet" switch, it simply reminds you that it in not possible to run an applet at the command line.
Usage: qfc [-standard] [-applet] [-html] filename
This command is used to compile a QuickFire program to a Java class file. At present there are two compilation modes "-standard" and "-applet".
"-standard" is suitable for generating QuickFire programs that can be run from the command line using the "qfr" command. Standard mode doesn't contain the runtime library functions specific to applets.
"-applet" is suitable for generating Java class files that can be used in a web page. These class files cannot be executed from the command line using the "qfr" command.
"-html" tells the compiler to generate a simple HTML file to load your compiled QuickFire Applet. This file should be placed on your web server together with the generated class file and QuickFireRuntime.jar found in QuickFireApp. The default setting is to not generate a HTML file this prevents you losing any customisations you may have made to the file.
Usage: qfr [-standard] [-applet] filename
This command is used to run a QuickFire program that was compiled for the command line: "-standard". Although the command has a "-applet" switch, it simply reminds you that it in not possible to run an applet at the command line.
Usage: vdm
This commands starts the Virtual Disk Manager which allows you to perform the following tasks:-
1. Load a virtual disk image
2. Save a virtual disk image
3. Get directory of files within a virtual disk
4. Delete files within a virtual disk
5. Rename files within a virtual disk
6. Import files into the virtual disk from the current directory on the host file system.
7. Export files from the virtual disk to the current directory on the host file system.
Firstly, we are making the assumption that the web server has been configured in such a way that it is possible to create restricted web pages. If you have any problems then you should check with your system administrator to ensure that restricted pages are enabled.
Once this section has been completed without errors your QuickFire server will be able to maintain many different users each with there own set of virtual disks.
This descriptions in this section are all for Linux / Unix Systems running Apache. If you are using another system then you will have to consult with your system administrator.
PHP runs as within the Web Server which is typically running under a different user and this currently has a major implication. Virtual Disk images need to be writable by the PHP page so you must arrange for the images to be writable by the user that Apache is running as. If you are the system administrator then this is quite easy to achieve however most people won't have that level of access. Currently the simplest way most users can give apache write access to their virtual disk images is simply to adjust the file protection.
chmod 777 virtualDisk.qfd
Automatic Security Configuration for Apache using apache.setup script
Most UNIX System running apache can be setup using the supplied apache.setup script supplied in the "bin" directory. To use this script, simply move into "QuickFireApp" and issue the command "bin/apache.setup". If "htpasswd" is in your path then this will be used by default. If it cannot be located then you will have to enter the full path to "htpasswd" when prompted. You will also be prompted for a password for the guest account Once all the information has been supplied, the script creates a simple ".htaccess" and ".htpasswd" file in the current directory.
Manual Security Configuration for Apache
AuthUserFile /INSERT_PATH_TO_QuickFireApp/.htpasswd
AuthName "QuickFire Development Environment"
AuthType Basic
require valid-user
htpasswd bc .htpasswd guest password
You may want to set-up additional remote users each with their own storage area. This can be done by following the steps listed below (remember to replace USERNAME and PASSWORD with appropriate values):-
cd QuickFireApp
mkdir USERNAME
htpasswd b .htpasswd USERNAME PASSWORD
cd USERNAME
vdm
> create blank.qfd
> quit
chmod 777 blank.qfd
cd ..
Anyone who has programmed using the "C" programming language should instantly feel at home with QuickFire. There are a few differences between the two languages, the main ones being listed below:-
The intention is that QuickFire will move nearer to "C" over time so it is likely that many of the missing "C" features will be addressed.
lvalue - An lvalue is anything that is allowed to appear on the left hand side of an assignment statement. It is anything that equates to a named storage item. Thus, "aVariable", "aArray[3]" are lvalues whereas "3", "aVariable * 5" are not.
rvalue - A rvalue is anything that is allowed to appear on the right hand side of an assignment statement. They may be either named storage items or the results of some expression or function call.
line no | program source (Example 1)
--------+---------------------------
1 | void main()
2 | print ("Hello, World!");
The program illustrates features that are common to all QuickFire programs and these features are described below.
Line 1 contains the function declaration "void main()" - This defines a function called "main" defines as returning "void". void simply means that the function will not return anything. A function name of "main" tells QuickFire that this is where program execution should begin once the program is started. The function name is followed by a list of arguments enclosed within parenthesis. In the case of the "main" function the argument list must be empty. Every program must have one, and only one, main function.
Each function must have a function body which describes the operation of the function. The function body is a single statement that immediately follows the function declaration and this is the purpose of line 2.
Line 2 simply contains "print ("Hello, World!")" followed by a semicolon which is used to terminate every statement. This is the instruction that is executed when the main function is called.
A function body consisting of A single statement doesn't seem very useful. What happens if we need to use more than one statement. As an example we will split the previous "print("Hello, World!")" into two statements.
line no | program source (Example 2)
--------+---------------------------
1 | void main()
2 | print ("Hello, ");
3 | print ("World!");
Line 1 & 2 operates in the same way as Example 1". What happens when line 3 is reached. Line 3 is not the same statement as line 2 so only the statement in line 2 is included as the function body. Line 3 stands by itself outside of any function body and causes an error to be issued when parsed.
To overcome this problem we now introduce the compound statements operators that allow many statements to be grouped together and treated as a single statement. A compound statement is started by the "{" character and terminate by the matching "}" character. Between the "{" and "}" characters you may place any number of executable statements, each terminated with a semicolon.
line no | program source (Example 3)
--------+---------------------------
1 | void main()
2 | {
3 | print ("Hello, ");
4 | print ("World!");
5 | }
Compound statements are common features in QuickFire programs and there use in usually found in conjunction with function bodies, loop constructs and decision making constructs.
Comments are sections of non-executable text that are ignored by the compiler. Comments are used for many things including describing what a piece of code does, how it operates, how it is used, who wrote it and when it was
it was written.
QuickFire supports the "C" style "/* .. */" comments and the "C++" "//" comments.
The "C" style comments is started with the "/*" sequence and everything is ignored up to the next "*/" sequence. This comment format is used to comment out blocks of code that may spread over many lines.
The "C++" style comment is used to ignore everything else on the current line.
Example 4 (below) illustrates both of these comment formats.
line no | program source (Example 4)
--------+---------------------------
1 | /*
2 | * This program prints "Hello, World!"
3 | */
4 | void main() // Function declaration
5 | { // Compound statement start
6 | print ("Hello, "); // Print "Hello, "
7 | print ("World!"); // Print "World!"
8 | } // Compound statement end
QuickFire currently supports the following data types:-
int - 32 bit signed integer data type
long - 64 bit signed integer data type;
float - 32 bit IEEE floating point data type;
double - 64 bit IEEE double precision data type.
string - String data type
void - used to indicate that a function doesnt return a value;
Constants are used to define invariant values i.e. Values that never change during program execution.
Integer constants are 32 bit signed integers (whole numbers) ranging between -2147483648 and +2147483547. By default, Integer constants are in decimal but you can use hexadecimal by preceding the integer with 0x or 0X.
Long constants are 64 bit signed integers (whole numbers). They are represented by appending a "L" or "l" to the end of the number. By default, Long constants are in decimal but you can use hexadecimal by preceding the long with 0x or 0X.
Float constants are 32 bit IEEE floating point numbers. They are represented as either a simple floating point value or specified in exponential format. Some examples of floating point constants follow:-
Source Code | Actual Value
------------+-------------
3.142 | 3.142
3.142E1 | 31.42
3.142E-1 | 0.3142
31.42E-1 | 3.142
Double constants are 64 bit IEEE floating point numbers. They are represented as either a simple floating point value or specified in exponential format.
Source Code | Actual Value
------------+-------------
3.142 | 3.142
3.142E1 | 31.42
3.142E-1 | 0.3142
31.42E-1 | 3.142
String constants are any sequence of characters enclosed within double quotation marks. E.g. "This is a string"
Variables and Variable Declaration
Variables are used to store values that are calculated and modified during execution of the program. Each variable is associated with a particular data type and a unique variable name. Variables names consist of a initial alphabetic or "_" character followed by any number of alphanumeric or "_" characters. The compiler distinguishes between upper and lower case letters therefore "varname" is a different variable from "varName".
Variables are defined by specifying a data type and then supplying a comma separated list of variable names. The list of variables is terminated with a semicolon.
line no | program source (Example 5)
--------+---------------------------
1 | int i_global;
2 | float f1_global, f2_global, f3_global;
3 | void main()
4 | {
5 | long l_local;
6 | }
Variables may be defined ever inside or outside functions.
If a variable is defined inside a function then it is available only within that function. If a variable is defined outside a function then it is globally available to all functions.
Variables are assigned values using the assignment "=" operator. The value of a variable is accessed by simply inserting the variable name wherever you would use a constant.
line no | program source (Example 6)
--------+---------------------------
1 | void main()
2 | {
3 | int a, b, c; // Define three variables
4 | a = 3; // Assign 3 to "a"
5 | b = 5; // Assign 5 to variale "b"
6 | c = a; // Assign value Of "a" (3) to "c"
4 | }
The cast operators are a series of unary operators that convert a value to the same value in another type. In some cases there can be a loss of precision during the conversion which is an unavoidable consequence stemming from the fact that the different types all have varying degrees of precision.
lvalue = (type)rvalue
value| (int)| (long)| (float)| (double)| (string)
---------+---------+---------+---------+---------+---------
123 | 123 | 123L | 123.0 | 123.0 | "123"
3.142 | 3 | 3L | 3.142 | 3.142 | "3.142"
0x1f | 31 | 31L | 31.0 | 31.0 | "31"
"one" | invalid | invalid | invalid | invalid | invalid
line no | program source (Example 7)
--------+---------------------------
1 | void main()
2 | {
3 | double PI;
4 | PI = 3.14159265359; // Assign value of PI
5 | print ((string)PI); // print takes a string
6 | }
In many cases the compiler automatically ensures that the operands are of the same types. This process is known as coercion and involves the compiler automatically casting values to the required type. Where operations need compatible types coercion will always be performed even if you have explicitly applied a cast.
Where coercion is necessary you can find the common type from the following table.
| int | long | float | double | string
---------+---------+---------+---------+---------+---------
int | int | long | float | double | string
long | long | long | float | double | string
float | float | float | float | double | string
double | double | double | double | double | string
string | string | string | string | string | string
As you would expect the usual arithmetic operators are available to perform addition (+), subtraction (-), multiplication (*) and division (/). These operators all take two source operands separated by the required operator. If the two source operands are not the same type then the compiler will automatically coerce the operands to the same type. The type of the result value is always the same as the source operands.
src1 | operator | src2 | result | Example
-----+----------+------+--------+---------------
5.0 | + | 3.0 | 8.0 | a = 5.0 + 3.0;
5.0 | - | 3.0 | 2.0 | a = 5.0 - 3.0;
5.0 | * | 3.0 | 15.0 | a = 5.0 * 3.0;
5.0 | / | 3.0 | 1.666 | a = 5.0 / 3.0;
There is a special form of the addition operator (+) for strings. In this case the {+} operator performs string concatenation. i.e. The second string is appended to the end of the first string. String concatenation is implied if one or both of the source operands are strings. If one of the operands is a numeric data type then it will be automatically coerced into a string. This allows you to print out the value of variable.
src1 | operator | src2 | result | Example (string s)
-------+----------+--------+-----------+-------------------
"S1," | + | " S2" | "S1, S2" | s="S1," + " S2";
"val=" | + | 5.0 | "val=5.0" | s = "val=" + 5.0;
5.0 | + | "cm" | "5.0cm" | s = 5.0 + "cm";
The remainder operator (%) performs a division between two integers (int or long) and returns the remainder.
src1 | operator | src2 | result | Example
-----+----------+------+--------+-----------
5 | % | 4 | 4 | a = 5 % 4;
5 | % | 5 | 0 | a = 5 % 5;
The unary minus operator is used by simply placing a minus sign immediately before the operand you wish to negate.
Negation simply means changing the sign, thus if the operand was positive the result will be the same value but with a negative sign. Likewise if the operand was negative the result will be the same value except positive.
operator | src | result | Example
---------+-----+--------+-----------
- | 5 | -5 | a = -5;
- | -5 | 5 | a = -(-5);
The Parenthesis operators, "(" and")", are used to groups operators so that the expression is evaluated in a specific order. Operations within parenthesis have a higher priority than, and are executed before, operators outside the parenthesis.
line no | program source (Example 8)
--------+---------------------------
1 | void main()
2 | {
3 | double a, b, c; // Define three variables
4 | a = 3 * 4 + 5; // Assign 17 to "a"
5 | b = (3 * 4) + 5; // Assign 17 to "b"
6 | c = 3 * (4 + 5); // Assign 27 to "c"
4 | }
The increment operator is used to add one to the associated variable. There are two forms of the increment operator - pre increment and post increment.
Pre increment refers to the fact that the result is obtained after the variable has been incremented. Pre Increment is indicated by placing "++" before the variable to be incremented.
Post increment refers to the fact that the result is obtained before the variable has been incremented. Post Increment is indicated by placing "++" after the variable to be incremented.
| start value | ++val | val++ | final value
| of variable | result | result | of variable
---------+--------------+--------+--------+------------
int i | 123 | 124 | 123 | 124
long l | 123 | 124 | 123 | 124
float f | 123.0 | 124.0 | 123.0 | 124.0
double d | 123.0 | 124.0 | 123.0 | 124.0
string s | "123" | "1231" | "123" | "1231"
The decrement operator is used to subtract one from the associated variable. There are two forms of the decrement operator - pre decrement and post decrement.
Pre decrement refers to the fact that the result is obtained after the variable has been decremented. Pre decrement is indicated by placing "--" before the variable to be incremented.
Post decrement refers to the fact that the result is obtained before the variable has been decremented. Post decrement is indicated by placing "--" after the variable to be incremented.
| start value | --val | val-- | final value
| of variable | result | result | of variable
---------+--------------+--------+--------+------------
int i | 123 | 122 | 123 | 122
long l | 123 | 122 | 123 | 122
float f | 123.0 | 122.0 | 123.0 | 122.0
double d | 123.0 | 122.0 | 123.0 | 122.0
Note that no example is given for a pre/post decrement of a string value since it is an invalid operation.
Relation expressions and operators
Relational operators produce a logical true/false (1/0) results based on the result of the comparison between the operand. Although we refer to true / false values these are actually represented as integer values 0 and 1 which are stored in int and long data types. Values other than 0 and 1 are also treated as true but there use is discouraged.
src1 | src2 | == | != | < | <= | > | >= |
5 | 5 | true|false|false| true|false| true|
4 | 5 |false| true| true| true|false|false|
6 | 5 |false| true|false|false| true| true|
The result of relational expressions are commonly used by Control flow and Looping constructs which are described in the next two sections.
The basic decision making statement is the "if" statement which takes the following form:-
if (relational_expression) statement;
This simply states that if the relational expression is true then execute the supplied statement.
A variation of the "if" statement allows you to also specify a statement to be executed if the relational expression is not true. This clause is introduced with the "else" keyword. The format of the "if ... else" statement is:-
if (relational_expresssion) statement1 else statement2;
This simply states that if the relational expression is true then execute the statement1 otherwise execute statement2.
Whilst the statements are commonly compound statements it is not unusual to see single statements being used.
There are three kinds of loops in QuickFire: The "while" loop, "do while" loop and finally the "for" loop.
The "while" loop repeats a statement while a relational expression produces a true result. The statement may be executed zero or any number of times depending on the result of the supplied relational expression. The syntax of the while loop is :-
while (relational_expression) statement;
The "do while" loop is similar to the while loop except that the relational expression is tested at the end of the loop. If the relational expression produces a true result then another iteration of the loop is performed. The statement is always executed at least once and may be executed any number of times. The syntax of the do while loop is:-
do statement while (expression);
The final loop is the "for" loop. This loop is consists of an initialisation expression, a test expression, an increment expression and a statement. The format is shown below:-
for (init; test; incr) statement
The "init" expression is executed once immediately before the loop is started. The "init" expression is intended to be used to set the initial condition of the loop.
The "test" relational expression is executed immediately before the statement is executed. If the "test" expression produces a true result then the statement is executed otherwise the loop is terminated and execution continues with the statement following the loop.
Once the supplied statement has been executed the "incr" expression is executed. This expression is intended to be used to increment the control variable(s). Although its called an increment expression you can in fact perform any calculation. After execution of the "incr" expression the next iteration of the loop is started, starting with the "test" expression.
Sometimes it is necessary to break out of a loop immediately without any further instructions within the loop body being executed and without the loop control expression being evaluated.
The keyword that does this is the "break" keyword.
Likewise, at times it is necessary to immediately start the next iteration of the loop without executing any further instruction in the loop body for the current iteration.
The keyword that performs this action is the "continue" keyword.
Bitwise operators work on the individual bits and may only be applied to integer operands (i.e. int and long). There are several bitwise operators including AND (&), OR (|), exclusive OR (^), Complement bits (~), Shift Bits Left (<<), Shift bits right (>>) and shift bits right with sign extension (>>>).
Both operands are coerced to the same type. The result is always the same as the two input types.
The bitwise AND (&) operator takes two integer operands. A bitwise AND looks at each individual bit within the first operand and compares it with the corresponding bit in the second operand. If both bits are 1 then the corresponding bit in the result will also be a 1 otherwise it will be zero. The following truth table illustrates the relationship:-
AND| 0 | 1
---+---+---
0 | 0 | 0
1 | 0 | 1
example: lvalue= rvalue & rvalue
The bitwise OR (|) operator takes two integer operands. A bitwise OR looks at each individual bit within the first operand and compares it with the corresponding bit in the second operand. If either bits are 1 then the corresponding bit in the result will also be a 1 otherwise it will be zero. The following truth table illustrates the relationship:-
OR| 0 | 1
---+---+---
0 | 0 | 1
1 | 1 | 1
The bitwise exclusive OR (^) operator takes two integer operands. A bitwise exclusive OR looks at each individual bit within the first operand and compares it with the corresponding bit in the second operand. If one, and only one, of the bits is 1 then the corresponding bit in the result will also be a 1 otherwise it will be zero. The following truth table illustrates the relationship:-
XOR| 0 | 1
---+---+---
0 | 0 | 1
1 | 1 | 0
The bit complement operator is a unary operator which takes a single integer operand. Each bit in the operand is inverted. i.e. If the bit was 0 then the output bit will be 1, likewise if the bit was 1 then the output bit will be a 0. The following table illustrates the operation.
in | out
----+----
0 | 1
1 | 0
The three bitwise shift operators each take two integer operands. The first operand contains the value to be shifted and the second operand contains the number of bits it is to be shifted by.
Since the size of a int is 32 bits there would be little point in shifting anything more than 31 bits (left or right) since the answer would be always zero. Likewise there would be little point in shifting a long by more than 63 bits for the same reason. NOTE: If you were using shift right with sign extension then the final value under these circumstances would be either 0 or 1 depending on the initial value of the sign bit.
The left shift operand shifts all the bits to the left. Each time a bit is shifted to the left a 0 bit is shifted into bit 0. Bits shifted out of the most significant bit are lost. A left shift by 1 is equivalent to doubling the value of an integer or multiplying by two. A left shift of 2 is equivalent to multiplying by four. A left shift of n is equivalent to multiplying by 2 to the power n.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---+---+---+---+---+---+---+---+
Before 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
<< 1 | 0 | 1 | 1 | 0 | 1 | 1 | 0 |
The right shift operand shifts all the bits to the right. Each time a bit is shifted to the right a 0 bit is shifted into the most significant bit. Bits shifted out of bit 0 are lost. A right shift by 1 is equivalent to halving the value of an unsigned integer or dividing by two. A right shift of 2 is equivalent to dividing by four. A right shift of n is equivalent to dividing by 2 to the power n.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---+---+---+---+---+---+---+---+
Before 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
>> 0 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
The right shift with sign extension operand shifts all the bits to the right. The most significant bit is always left unchanged. Bits shifted out of bit 0 are lost. A right shift with sign extension by 1 is equivalent to halving the value of an signed integer or dividing by two. A right shift with sign extension of 2 is equivalent to dividing by four. A right shift with sign extension of n is equivalent to dividing by 2 to the power n.
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---+---+---+---+---+---+---+---+
Before 1 | 1 | 0 | 1 | 1 | 0 | 1 | 1 |
>>> 1 | 1 | 1 | 0 | 1 | 1 | 0 | 1 |
Logical operators are used in conjunction with relational expressions. They are used when you want to specify that two or more relational expression must be matched, or if one or the other relational expression must be matched.
if ((a < 10) && (b == 20))
print ("a is less than 10 AND b is equal to 20");
if ((a < 10) || (b == 20))
print ("a is less than 10 OR b is equal to 20");
src1| src2| && | || |
-----+-----+-----+-----+
false|false|false|false|
false| true|false| true|
true|false|false| true|
true| true| true| true|
An additional NOT operators allows you to negate the result of an expression.
src | !
-----+-----
false| true
true|false
int i;
i = 5;
if (i == 5)
print ("i is equal to 5");
if (!(i == 5))
print ("i is not equal to 5");
In common with the "C" programming language, there are several variations on the assignment operator.
lvalue Χ= rvalue lvalue = lvalue Χ rvalue
lvalue /= rvalue lvalue = lvalue / rvalue
lvalue %= rvalue lvalue = lvalue % rvalue
lvalue += rvalue lvalue = lvalue + rvalue
lvalue -= rvalue lvalue = lvalue - rvalue
lvalue &= rvalue lvalue = lvalue & rvalue
lvalue |= rvalue lvalue = lvalue | rvalue
lvalue ^= rvalue lvalue = lvalue ^ rvalue
A function is a small section of code consisting of a sequence of instructions. A Function typically define and implement a single well defined operation. A function allows a sequence of operations to be executed from many places in the program without the code being duplicated.
A function consists of a return value, a function name, a list of arguments and a sequence of statements to be executed when the function is called.
Functions that return a value will also have one or more return statement which are used to signal the end of the function and to pass a return value back to the caller. A void function doesn't need a return statement.
line no | program source (Example 9)
--------+---------------------------
1 | int doubleIt(int inputValue)
2 | {
3 | int outputValue;
4 | outputValue = inputValue + inputValue;
5 | return outputValue;
6 | }
7 |
8 | void main()
9 | {
10 | int x;
11 | x = 27;
12 | print ("x = " + x);
13 | print ("doubleIt(" + x + ")=" + doubleIt(x));
14 | }
Line 1 defined a function called "doubleIt" it returns a int result and accepts a single int argument which will be known as "inputValue" within the function.
Line 4 calculates the value to be returned.
Line 5 instructs QuickFire to pass the value of "outputValue" back to the calling instruction in line 13.
Line 13 calls the doubleIt() and passes doubleIt() the value of x (27). doubleIt() calculates the result and returns 54.
QuickFire currently only supports one dimensional arrays. An array is specified in one of two ways:-
1. This first method is to append "[num]" after the type. For example: "int[num] a;". In this case all variables defined after the type will be integers arrays containing "num" elements.
2. The second method is to append "[]" after the variable name. For example: "int a[num];". In this case only the variables with "[num]" appended will be arrays containing "num" elements.
When arrays are passed to and returned from functions you should simply append "[]" to the type or variable and not specify the number of elements.
line no | program source (Example 10)
--------+---------------------------
1 | void reverseArray(int[] iArray, int n)
2 | {
3 | int i;
4 | for (i=0;i<n/2;i++)
5 | {
6 | int t;
7 | t = iArray[i];
8 | iArray[i] = iArray[n-i-1];
9 | iArray[n-i-1] = t;
10 | }
11 | }
12 |
13 | float[] convertArray(int[] iArray, int n)
14 | {
15 | float fArray[10];
16 | int i;
17 |
18 | for (i=0;i<n;i++)
19 | fArray[i] = (float)iArray[i];
20 |
21 | return fArray;
22 | }
23 |
24 | void main()
25 | {
26 | int iArray[10];
27 | float[] fArray;
28 | int i;
29 | for (i=0;i<10;i++)
30 | iArray[i] = i;
31 | reverseArray(iArray, 10);
32 | fArray = convertArray(iArray, 10);
33 | for (i=0;i<10;i++)
34 | print ("fArray[" + i + "]=" + fArray[i]);
35 | }
Pass by Value and Pass by Reference
In common with "C", QuickFire passes all non-array function arguments by value. Any modifications to the arguments within the function are purely local to the function. i.e. The original values in the calling function are not modified.
QuickFire passes arrays by reference. A function cannot change any characteristics of the array however it may change individual values it holds. These changes take effect immediately and all future references to the array in the function and in the calling function will produce the same result.
= += -= *= /= %= |= &= ^=
||
&&
|
^
&
== !=
< <= > >=
<< >> >>>
+ -
Χ χ %
UNARY ++ -- ! ~
( )
QuickFire contains a runtime library that consists of several main components designed to help you write applets. The runtime library has been designed to be extensible although this is not within the scope of this manual.
These string functions provide basic facilities for accessing and manipulating strings. The available functions allow you to extract sections of a string, get the length of a string and search for a substring within a string.
Usage: string charstr(int ascii)
The function returns the string equivalent of an ASCII value. For example, charstr() returns "A" when you pass it a value of 65.
void main()
{
int width;
int height;
int lastKey;
int key;
width = DisplayWidth();
height = DisplayHeight();
lastKey = -1;
Refresh(-1);
do
{
key = Inkey();
if (key != lastKey)
{
SpriteClearArea(0, 0, 0, width, height);
SpriteSetColour(0, 0xaaaaaa);
SpritePrintCenter(0, "Click on window and press key", width/2, height/4*1);
SpritePrintCenter(0, "charstr(" + key + ")=" + charstr(key), width/2, height/4*2);
SpritePrintCenter(0, "Press return to finish", width/2, height/4*3);
lastKey = key;
Refresh(0);
}
} while (key != 10);
}
Usage: string midstr(string str, int offset, int nchar)
midstr() takes a string a returns a substring containing "nchars" consecutive characters starting at "offset". For example, midstr("String", 2, 2) returns "ri".
Usage: string leftstr(string str, int nchar)
leftstr() takes a string a returns a substring containing the leftmost "nchars" characters. For example, leftstr("String", 2) returns "St".
Usage: string rightstr(string str, int nchar)
rightstr() takes a string a returns a substring containing the rightmost "nchars" characters. For example, rightstr("String", 2) returns "ng".
Usage: int strlen(string str)
strlen() takes a string and returns the number of characters within the string. For example, strlen("String") will return a value of 6.
Usage: int strpos(string str1, string str2, int offset)
strpos() searches str1 for an occurrence of str2 starting from the specified offset. The function returns either the offset of str2 in str1 or -1 if it wasnt found. For example, strpos("String", "ring", 0) returns 2 but strpos("String", "RING", 0) returns 1.
All file Input/Output is handled by the external functions listed below. Access is performed by either creating a new file (create())or opening an existing file (open()). Both of these functions take a filename and return an integer file descriptor. The file descriptor is then used in all future I/O operations.
line no | program source (Example 1)
--------+---------------------------
1 | void main()
2 | {
3 | string filename;
4 | int fd;
5 |
6 | filename = "filename.dat";
7 |
8 | fd = open(filename);
9 | if (fd == -1)
10 | {
11 | fd = create(filename);
12 | if (fd != -1)
13 | {
14 | writeByte(fd, 1);
15 | writeShort(fd, 2);
16 | writeInt(fd, 3);
17 | writeLong(fd, 4L);
18 | writeFloat(fd, (float)5.0);
19 | writeDouble(fd, 6.0);
20 | writeString(fd, "Hello, World!");
21 | close(fd);
22 | }
23 | else
24 | {
25 | print ("Bytes available = " + eof(fd));
26 | print ((string)readByte(fd));
27 | print ((string)readShort(fd));
28 | print ((string)readInt(fd));
29 | print ((string)readLong(fd));
30 | print ((string)readFloat(fd));
31 | print ((string)readDouble(fd));
32 | print ((string)readString(fd));
33 | close(fd);
34 | }
35 | }
36 | }
Usage: int open(String filename)
The open() function is used to open an existing file for read only accesss. It take a single string argument which is used as the name of the file. The function attempts to open the file and returns either the integer file descriptor or -1 if there was an error.
Usage: int create(String filename)
The create() function is used to create a new file which is opened for write only accesss. It take a single string argument which is used as the name of the file. The function attempts to create the file and returns either the integer file descriptor or -1 if there was an error.
Useage: int close(int fd)
The close() function takes a file descriptor and flushes any unwritten data to the file. Finally the file is closed and you may not perform any further operations on the specified file descriptor.
Usage: int eof(int fd)
eof() returns the number of bytes remaining until EOF. Each time a byte is read the value returned by eof() will be decremented by one. A returned value of zero indicates that the end of file has been reached and there is no more data available. A returned value of -1 indicates that there was an error.
Usage: int readByte(int fd)
readByte() reads a single signed byte (8 bits) from the stream indicated by "fd". If no data is available then readByte() returns zero, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readByte().
Usage: int readShort(int fd)
readShort() reads a single signed short (16 bits) from the stream indicated by "fd". If no data is available then readShort() returns zero, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readShort().
Usage: int readInt(int fd)
readInt() reads a single signed int (32 bits) from the stream indicated by "fd". If no data is available then readInt() returns zero, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readInt().
Usage: long readLong(int fd)
readLong() reads a single signed long (64 bits) from the stream indicated by "fd". If no data is available then readLong() returns zero, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readLong().
Usage: float readFloat(int fd)
readFloat() reads a single float (32 bits) from the stream indicated by "fd". If no data is available then readFloat() returns zero, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readFloat().
Usage: double readDouble(int fd)
readDouble() reads a single double (64 bits) from the stream indicated by "fd". If no data is available then readDouble() returns zero, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readDouble().
Usage: String readString(int fd)
readString() reads a string from the stream indicated by "fd". If no data is available then readString() returns an empty string, therefore it is essential that you check the end of file has not been reached by calling eof() before calling readDouble().
Usage: int writeByte(int fd, int bVal)
writeByte() writes the signed byte specified by bVal to the specified file descriptor (fd). writeByte() returns the number of bytes written (1) or zero if there was an error.
Usage: int writeShort(int fd, int sVal)
writeShort() writes the signed short specified by sVal to the specified file descriptor (fd). writeShort() returns the number of bytes written (2) or zero if there was an error.
Usage: int writeInt(int fd, int iVal)
writeInt() writes the signed int specified by iVal to the specified file descriptor (fd). writeInt() returns the number of bytes written (4) or zero if there was an error.
Usage: int writeLong(int fd, long lVal)
writeLong() writes the signed long specified by lVal to the specified file descriptor (fd). writeLong() returns the number of bytes written (8) or zero if there was an error.
Usage: int writeFloat(int fd, float fVal)
writeFloat() writes the float specified by fVal to the specified file descriptor (fd). writeFloat() returns the number of bytes written (4) or zero if there was an error.
Usage: int writeDouble(int fd, double dVal)
writeDouble() writes the float specified by dVal to the specified file descriptor (fd). writeDouble() returns the number of bytes written (8) or zero if there was an error.
Usage: int writeString(int fd, String stringVal)
writeString() writes the String specified by stringVal to the specified file descriptor (fd). writeString() returns the number of bytes written or zero if there was an error.
Usage: double sin(double exp)
sin() takes a value and computes its Sine in Radians. The computed value is returned as the function's result.
Usage: double asin(double exp)
asin() takes a value and computes its Arc Sine in Radians. The computed value is returned as the function's result.
Usage: double cos(double exp)
cos() takes a value and computes its Cosine in Radians. The computed value is returned as the function's result.
Usage: double acos(double exp)
acos() takes a value and computes its Arc Cosine in Radians. The computed value is returned as the function's result.
Usage: double tan(double exp)
tan() takes a value and computes its Tangent in Radians. The computed value is returned as the function's result.
atan() - Arc-Tangent (Radians)
Usage: double atan(double exp)
atan() takes a value and computes its Arc Tangent in Radians. The computed value is returned as the function's result.
Usage: double sind(double exp)
sind() takes a value and computes its Sine in Degrees. The computed value is returned as the function's result.
Usage: double asind(double exp)
asind() takes a value and computes its Arc Sine in Degrees. The computed value is returned as the function's result.
Usage: double cosd(double exp)
cosd() takes a value and computes its Cosine in Degrees. The computed value is returned as the function's result.
acosd() Arc-Cosine (Degrees)
Usage: double acosd(double exp)
acosd() takes a value and computes its Arc Cosine in Degrees. The computed value is returned as the function's result.
Usage: double tand(double exp)
tand() takes a value and computes its Tangent in Degrees. The computed value is returned as the function's result.
atand() Arc-Tangent (Degrees)
Usage: double atand(double exp)
atand() takes a value and computes its Arc Tangent in Degrees. The computed value is returned as the function's result.
Usage: double sqrt(double exp)
sqrt() takes a value and computes its Square root. The computed value is returned as the function's result.
Usage: double log(double exp)
log() takes a value and computes its Natural Logarithm. The computed value is returned as the function's result.
Usage: double exp(double exp)
exp() takes a value and computes e to the power of the supplied value. The computed value is returned as the function's result. exp() is the inverse of log().
log10() Logarithm in Base 10
Usage: double log10(double exp)
log10() takes a value and computes its Base 10 Logarithm. The computed value is returned as the function's result.
Usage: double pow(double x, double y)
pow() takes two values and raises the first value to the power of the second. The computed value is returned as the function's result. pow() can be used to inverse base 10 logarithms using pow(10.0, log10value).
random() Returns random number between 0.0 and 1.0 inclusive
Usage: double random(double exp)
random() returns a random value between 0.0 and 1.0 inclusive.
Different computers and browsers operate at vastly different speeds. The Throttle functions are designed to allow the program to run at the same speed irrespective of the final platform.
If a program is running too slowly then you can stop processing optional parts of your program. If there are items rotating then you can either not rotate the objects or reduce the number of times that they are rotated possibly by replacing 10 small 1 degree rotation with a single rotation of 10 degrees. Another option is reduce the refresh rate by calling Refresh() with another value.
Likewise, if you find that you have more time available then the program can use a higher refresh rate, finer rotations and any optional processing.
An example of using the throttle functions is shown below. This example simply adjust the display refresh rate according to how much extra processing time is available.
/*
* Set initial Refresh Rate to 50
*/
int refreshRate;
refreshRate = 50;
Refresh(refreshRate);
ThrottleSet (1000/50);
while (mainLoopRunning)
{
int time;
time = ThrottleTime();
if (time > 0) // Extra time available!
{
if (time > 1000/25) // Don't change anything
{ // until there is a lot extra!
if (refreshRate < 50) // If refresh rate is < 50
{
refreshRate++; // Increase refresh rate
Refresh(refreshRate);
}
Sleep(time); // Use up extra time
}
}
else if (time < 0) // Program is going too slow!
{
if (refreshRate > 5) // If refresh rate is > 5
{
refreshRate--; // Decrease refresh rate
Refresh(refreshRate);
}
}
Usage: void ThrottleSet(int milliseconds)
ThrottleSet is supplied with the number of milliseconds that should elapse between each call to ThrottleTime().
Usage: long ThrottleTime()
This function will return the number of milliseconds the program is running ahead or behind. It is important that you only call this function once to determine how much time you have left. If you need to use the value several times then you must buffer the value in a variable. A Positive number of milliseconds indicates that the programming is running too quickly and there is extra processing time available (the returned value is the number of milliseconds available). A negative number of milliseconds indicates that the program is taking too long and should reduce its processing if possible.
Usage: void Sleep(int ms)
Number of milliseconds to sleep.
Usage: void Yield()
Yield current thread.
Usage: int ffbs(long ival, int startBit)
Find and returns first bit set in ival starting from startBit. The returned value will be an integer from 0 to 63 or -1 if no set bit was found. This routine will be useful in dealing with collision detection specifically accessing the value returned by SpriteHit().
Usage: int ffbc(long ival, int startBit)
Find and returns first bit clear in ival starting from startBit. The returned value will be an integer from 0 to 63 or -1 if no clear bit was found. This routine will be useful in dealing with collision detection specifically accessing the value returned by SpriteHit().
Usage: void Refresh(int fps)
Refresh the screen where fps can be be values between -1 and 60. Values 1 to 60 specifiy a automatic screen refresh rate in frames per second. A value of 0 means that you wish to control when the screen is updated and the screen is only update when Refresh(0) is called. A value of -1 tells the system to temporarily disable screen refresh which is useful to prevent flickering. Dont forget to enable screen refreshes again by calling Refresh again!
Usage: void print (string str)
Prints str to the standard output.
Usage: int DisplayWidth()
Returns width of display area in pixels. When running QuickFire as an application the display width can be customised in the editor. When QuickFire is running as an applet within a web page, the width is determined by the <applet> tag within the web page. Wherever possible you should try to make sure that you are not making assumptions about the display width.
Usage: int DisplayHeight()
Returns height of display area in pixels. When running QuickFire as an application the display height can be customised in the editor. When QuickFire is running as an applet within a web page, the height is determined by the <applet> tag within the web page. Wherever possible you should try to make sure that you are not making assumptions about the display height.
Usage: int MouseX()
return X co-ordinate of mouse
Usage: int MouseY()
return Y co-ordinate of mouse
Usage: int MouseButton()
return state of mouse button 0=not pressed, 1=pressed.
Usage: int Getchar()
return value of last key typed.
Usage: int Inkey()
return value of last key typed but only if it is still pressed. Zero is returned if no key is pressed. See description of charstr() for an example of use.
A sprite is an independently moveable graphics object that overlays the main display. Although sprites are commonly used for animations and games we have chosen to make the sprite the central displayable object hence even the background is a sprite (sprite 0).
QuickFire currently supports 64 unique foreground sprites and a single background sprite. Each sprite has a number of properties which are listed below:-
Usage: long SpriteCollision(int spriteNum, long spriteMask)
Returns an integer containing 64 individual bits which indicate if the specified sprite has collided with sprite BITn + 1. A collision occurs if a sprite's non-transparent pixels (Drawn with colour -1) occupy the same screen position as another sprite. By default this routine will check all sprites for collision however you can specify a mask which restricts which sprites are tested for. Bit zero set = Check Sprite 1, Bit 63 set = Check Sprite 64. Collision detection with the background is performed by requesting the collision bits for the Background Sprite - i.e. Sprite 0. You can use ffbs() and ffbc() functions to search the returned value for collisions.
Usage: void SpriteClearArea(int spriteNum, int x1, int y1, int x2, int y2)
Clear rectangular area specified by (x1, y1, x2, y2).
Usage: void SpriteCopyArea(int spriteNum, int x1, int y1, int x2, int y2, int x3, int y3)
Move rectangular area specified by (x1, y1, x2, y2) to the location specified by (x3, y3). (x1,y1) specify the top left corner of the area to move while (x2, y2) specify the bottom right corner of the area to move.
Usage: int SpriteCount()
Returns number of Sprites excluding the background sprite. The routine currently returns 64 which means that foreground sprites 1 64 are available. The background sprite (Sprite 0) is not included in the count.
Usage: void SpriteCreate(int spriteNum, int numFrames, int w, int h)
Create sprite specified by spriteNumber, which currently ranges from 0 to 64. numFrames specifies the number of frames associated with the sprite (for sprite animations). The current frame is selected by SpriteSelectFrame(). The size of the sprite is specified by width and height arguments (in pixels). The width and height is constant for all images within the sprite.
Usage: void SpriteDrawTo(int spriteNum, int x, int y)
Draws a line from the current position to the specified co-ordinates using the currently selected colour. The current position is updated to reflect the end point of the line.
Usage: void SpriteFillArea(int spriteNum, int x1, int y1, int x2, int y2)
Fill rectangular area specified by (x1, y1, x2, y2) using the currently selected colour.
Usage: int SpriteFrameCount(int spriteNum)
Returns number of frames associated with specified sprite - each frame corresponds to an individual image.
Usage: int SpriteGetHeight(int spriteNum)
Return height of sprite in pixels.
Usage: int SpriteGetPixelAt(int spriteNum, int x, int y)
Returns pixel (RGB value + transparency & collision detection bits) at specified x, y co-ordinates.
Usage: int SpriteGetWidth(int spriteNum)
Return width of sprite in pixels.
Usage: void SpriteLoad (int spriteNum, String documentBaseURL, String relativeURL, int transparentPixel)
Load sprite with specified GIF or JPG file. documentBaseURL is used by applications (Applets already have a DocumentBase implied by the web page that was loaded). relativeURL is used by both applications and applets. More information on documentBaseURL and relativeURL can be found in the Audio Section.
Usage: void SpriteMerge(int src, int dest, int x, int y)
Overlays src sprite on dest sprite at location x, y. On return the destination sprite contains an imprint of the source sprite. The source sprite is rotated and scaled prior to imprinting on the destination sprite. The co ordinates of the source sprite are not taken into account so it is permissible for the source sprite to be off screen.
Usage: void SpriteMove(int spriteNum, int x, int y)
Move specified sprite to X and Y location.
Usage: void SpritePlot(int spriteNum, int x, int y)
Plots a pixel at the specified co-ordinates using the currently selected colour. The current position is updated to reflect the pixel location.
Usage: void SpritePolyBegin(int spriteNum, int x, int y)
This function is used to initiate a new filled polygon using the current colour. If the current colour is changed whilst the polygon is being defined then the new colour will apply to the polygon points which follow. The polygon drawing routines will smoothly shade between the colours.
A SpritePolyBegin() must always be followed by several SpritePolyDrawTo() calls and a trailing SpritePolyEnd() call. The polygon is not rendered on the screen until SpritePolyEnd() is called.
Usage: void SpritePolyDrawTo(int spriteNum, int x, int y)
This function is used to draw a line to the next point in the filled polygon. You must always call SpritePolyBegin() before calling SpritePolyDrawTo();
Usage: void SpritePolyEnd(int spriteNum)
This function is used to complete the filled polygon. The polygon is only drawn when this function is called. You must always call SpritePolyBegin() and SpritePolyDrawTo() prior to calling SpritePolyEnd().
Usage: void SpritePrintCenter(int spriteNum ,string str, int x, int y)
Prints str so that it is centred on the specified co-ordinates.
Usage: void SpritePrintLeft(int spriteNum, string str, int x, int y)
Prints str starting at x, y. i.e. The specified coordinates are to the left of the text.
Usage: void SpritePrintRight(int spriteNum ,string str, int x, int y)
Prints str so that the string finishes at x, y. i.e. The specified co-ordinates are to the left of the text.
Usage: void SpriteRotate (int spriteNum, double angle)
Rotate the sprite by the specified angle (in degrees)
Usage: void SpriteScale (int spriteNum, double xScale, double yScale)
Scales the sprite in both the x (width) and y (height) dimensions. Example values: 1.0 (no scaling), 2.0 (double), 0.5 (half).
Usage: void SpriteSelectFrame(int spriteNum, int frameNum)
Selects which image within the sprite is to be used in future operations. frameNum will range from 0 up to but not including the number specified in the call to SpriteCreate.
Usage: void SpriteSetColour(int spriceNum, int rgb)
Use the colour specified by rgb from this point onwards. Colour is typically set by specifying the RGB value in hex. For example, 0xrrggbb where rr, gg and bb are hex values from 00 to ff. A value of -1 (0xffffffff) is used to indicate transparent. Collision detection is disabled for a particular pixel by setting its sign bit (i.e. OR pixel value with 0x80000000).
Please note that the UK spelling of Colour is currently used.
The Audio Functions are used to manage sound effects. Although you can use WAV files please be aware that all Internet Browsers do not support them. To ensure that your sound samples can be heard by the majority of Browsers please consider converting your samples into SUN ".au" format. This format has several advantages they are smaller, are quicker to download and are supported across a wide number of browsers.
The basic usage of the Audio Function is illustrated below:-
AudioLoad("Boing", "http://yourhost.com/Audio/", "Sound.au");
AudioPlay("Boing");
AudioLoad loads a sound sample, which will be known as "Boing" from this point onwards.
You may be wondering why there are two filenames in AudioLoad(). The answer is that an applet running in a web browser can only load files from the server it was loaded from. This location is identified by something called a "DocumentBase" to which the relativeURL is appended to give the final URL. When QuickFire is started as a standalone application it doesn't have any defined "DocumentBase". A consequence of this is that we need to specify a default value for when a "DocumentBase" is not present.
The "DocumentBase" should end with a "/" character. The document base can specify both host and default directory.
Starting the above example using QuickFire started as a standalone application results in the audio clip being loaded from "http://yourhost.com/Audio/Sound.au".
If you start the above example over the Internet from http://anotherhost.com/Test/test.html" then "http://anotherhost.com/Test/" becomes the "DocumentBase". The audio clip will be loaded from "http://anotherhost.com/Test/Sound.au".
AudioLoad()
Usage: void AudioLoad(String clipName, String documentBaseURL, String relativeURL)
Load audio clip specified by documentBaseURL (applications) or relativeURL (applets). The clip will be identified by clipName in future Audio requests.
Usage: void AudioPlay(String clipName)
Play clipName once.
Usage: void AudioStart(String clipName)
Start playing clipName repetitively.
Usage: void AudioStop(String clipName)
Immediately stops playing the specified clip.
Usage: void AudioStopAll()
Immediately stops all sound that is playing.