------
WinC+-
------
What is C+-?
------------
C+- is just another dialect of C++. It hasn't own compiler, it has parser that just translates the code to C++ (it is unreadable, for compilation purposes only).
Key differences:
- identations (tabs or four spaces) instead of curly braces {}
- no semicolons ; needed
- parenthesis () isn't necessary for such constructions as: if..else if..else, for..., while..., switch
- new construction - repeat N
- do...while.... changed to do...repeat if...
- verbal aliases for boolean operators and some other operators
- useful and easy to remember aliases for some blocks of SDL code
- library lsdl with some functions to easily work with SDL (fonts and text drawing, sounds, graphics), arrays, strings, random numbers, console output
WinC+- is name of this package for Windows.
WinC+- package includes:
- Programmer's Notepad taken from http://www.pnotepad.org/ with some hotkeys (F8 runs make.bat, F5 - run.bat) and highlighting scheme pre-configured
- C+- to C++ parser (c+-.exe)
- MinGW and SDL 1.2-15
- All tools and dll's needed to compile and run your programs on Windows
- This document which provides some basic information about C+- and it's library, not more. You should be familiar with C++ to use C+-.
- Example game with example make.bat file.
Just write some source, place make.bat near that source and run it. It will convert your program to c++, then it will compile it with g++. It will also copy all needed dll's to folder with produced exe. Then you can run run.bat.
To use .bats without edition you must unpack this archive to C:
Make sure that path is C:\cpm\c+-.exe
put all your data files such as fonts, images and sound into data folder
after building main.exe and all needed dll's will appear in that folder
run.bat also will appear near your source files. run bat will run main.exe from data folder
WARNINGS:
- you must leave blank unidented line in the end of each source file
- you shouldn't insert blank lines without ident near the idented ones, it will break the identation
- you must provide at least 1 line for empty class constructors. Example:
class Dummy
public:
Dummy()
Dummy::Dummy()
0
- comment doesnt counts as line, but it may break identation. valid example:
Dummy::Dummy()
//dfjsj
0
invalid example:
Dummy::Dummy()
//dfjsj
0
another invalid example:
Dummy::Dummy()
//dfjsj
- you must provide comments as separate line, i.e. not combine comments and code
- you cant place comment at the end of the block:
while x<0
x--
//invalid comment position
printLine ( "this won't compile" )
while x<0
x--
//valid comment position
0
printLine ( "this will be compiled" )
Table of contents:
Hello, world!
Console output
Basic types
Operators
Boolean operators
Other aliases
do..repeat if
repeat N
switch
How to pause a program
Creating a window
Main game loop, resizable window
key presses and releases
Other evens brief overview
Cursor and mouse
Timing
window functions
clearWindow
setColor
drawing rectangles
random numbers
fonts and drawing text
More about strings
Image class
Sound class
Music
Files
Save/load example:
Arrays classes
Multithreading example
Circles, Lines and 2D float Vectors - see Version changes
Hello, world!
-------------
#include <lsdl>
int main()
print ("Hello, world!")
pause ( 1000 )
return 0
lsdl includes sdl headers (ttf, image, mixer) and: fstream, iostream, math, stdlib, string and conio
Console output
--------------
print ()
printLine ()
you can print numbers, char buffers or strings:
str text1 = "TEST"
char buffer[512];
sprintf ( buffer, "float: %f, int: %i, char: %c, string %s", 10.53f, 200, 'G', text1.getString() )
printLine ( text1 )
printLine ( buffer )
printLine ( 5 )
printLine ( 5.4f )
The same data can be used to print text drawText function, that will be described below.
Basic types
-----------
boolean:
bool b is false
symbolic:
char c = 'A'
str s = "hello"
numeric:
byte - unsigned 8bit (0 to 255)
sbyte - signed 8bit (-127 to 127)
int - signed 16bit (-32`767 to 32`767)
uint - unsigned 16bit (0 to 65`535)
long - signed 32bit (-2`147`483`647 to 2`147`483`647)
ulong - unsigned 32bit (0 to 4`294`967`295)
floating point:
float, and double (more detailed)
float = 1.22f
double = 2.44444d
Operators
---------
+ or plus
- or minus
assignment: = (alisases: is, now is equals, was set to, changes to, now is, is)
increment: ++ (alisases: increases, inc)
decrement: -- (alisases: decreases, dec)
multiplication: * (aliases: multiplied by, mul)
division: / (aliases: divided by, div)
+= (x+=5 equals x=x+5. aliases: increases by)
-= (x-=5 equals x=x-5. aliases: decreases by)
*= (x*=5 equals x=x*5. aliases: now is multiplied by)
/= (x/=5 equals x=x/5. aliases: now is divided by)
Boolean operators
-----------------
operator, alias:
== equals, is equal
!= not equals, is not equal, is not
> is greater than
< is less than
>= is equal or greater than
<= is equal or less than
&& AND
|| OR
Other aliases
-------------
class Child : public Parent is equal to class Child extends Parent
do..repeat if
-------------
Same as while, but will be executed at least one time
int www = 5
do
www--
repeat if www != 0
Notice that identation of repeat must be same as do's.
repeat N
--------
repeat 10
printLine ("test")
"test" will be printed ten times
switch
------
int z is 5
switch z
case 5:
printLine ( "5!" )
//don't forget breaks in the end of each case:
break
case 6:
printLine ( "6!" )
break
How to pause a program
----------------------
pause ( 1000 )
Use small pauses to unload CPU in cycles.
Creating a window
-----------------
//next program creates window and shows it for 1 sec
#include <lsdl>
int main()
createWindow ()
pause ( 1000 )
return 0
createWindow ( width, heigth )
Main game loop, resizable window
-------------------------------
#include <lsdl>
int wwidth = 500
int wheight = 350
int main ()
createResizableWindow ( wwidth, wheight )
setWindowTitle ( "Resizable window" )
bool bQuit = false
while bQuit is not true
measureTime ()
showTitleFPS ()
//drawing here:
//handling events here:
handle events
//this block is necessary if you've created resizable window
if window was resized
resize the screen
//in case you need wwidth and wheight for some game logic:
wwidth = new screen width
wheight = new screen height
if window was closed
bQuit = true
//no more drawing, showing what was drawn:
updateWindow ()
capFPS ( 60 )
quit()
return 0
key presses and releases
-------------------------------
#include <lsdl>
int wwidth = 640
int wheight = 480
int main ()
createResizableWindow ( wwidth, wheight )
setWindowTitle ( "Resizable window" )
bool bQuit = false
while bQuit is not true
measureTime ()
showTitleFPS ()
//drawing here:
//handling events here:
handle events
//this block is necessary if you've created resizable window
if window was resized
resize the screen
//in case you need wwidth and wheight for some game logic:
wwidth = new screen width
wheight = new screen height
if window was closed
bQuit = true
if key was pressed
if it was key SPACE
setColor ( 0xFFFFFF )
clearWindow ()
if it was key RETURN
setColor ( 0xFF0000 )
clearWindow ()
if key was released
if it was key F11
//true means, after toggling to windowed mode that window will be resizable again
toggleFullScreen ( 640, 480, true )
//no more drawing, showing what was drawn:
updateWindow ()
capFPS ( 60 )
quit()
return 0
Other evens brief overview
--------------------------
Events handling example:
------------------------
handle events
if mouse was moved
//do something.
// mouseX and mouseY is integers containing mouse positions,
// they updates automatically, you can use them:
mX = mouseX
mY = mouseY
if wheel was scrolled up
//do something
if wheel was scrolled down
//do something
if mouse button was pressed
//check what button
if mouse button was released
//this is how you check (use one word: left, middle or right):
if it was left/middle/right button
//do something
if key was pressed
//check what key
if key was released
//this is how you should check:
//special keys are capitalized
if it was key LEFT
//alphabetic keys are decapitalised
if it was key w
//motion.type=walk :-)
if it was key LSHIFT
//motion.type=run :-)
if it was key 1
//numeric keys
if it was key KP_1
//numpad keys
if it was key F1
//functional keys
if it was key LSHIFT
//left shift
if it was key RCTRL
//right control
if it was key SPACE
//etc. you can see other key names in sdl documentation
//enter is RETURN by the way
if window was resized
resize the screen
//getting new screen width
//necessary only if you need them:
WIDTH = new screen width
HEIGHT = new screen height
if window was closed
//set some bool that you check on every step of your cycle to false here
Cursor and mouse
----------------
hideCursor(), showCursor(), setCursorPos (x,y)
As said above mouseX and mouseY always contains current cursor position if you use handle events.
Timing
------
Put measureTime () at start of gameloop (loop, which takes input, renders screen and plays sounds)
capFPS (FPS) at end of that loop
getTicks() if you want to maintain your own deltaTime processing
deltaTime is integer which updates after calling measureTime () if there is capFPS (FPS) on the end of the loop. deltaTime contains delta time
showTitleFPS () sets title to FPS. Use after measureTime()
window functions
----------------
see definitions:
createWindow ( int width, int height )
createResizableWindow ( int width, int height )
createFullScreen ( int width, int height )
resizeWindow ( int w, int h, bool isResizable = false )
toggleFullScreen ( int w, int h, bool isResizable = false )
setWindowTitle ( str caption )
showTitleFPS()
clearWindow()
updateWindow()
clearWindow
-----------
there is 3 variants of clearWindow:
clearWindow () - clears with current color, set by setColor
clearWindow ( 255, 255, 255 ) - clears with white
clearWindow ( 0xFFFFFF ) - clears with white
setColor
--------
setColor ( 255, 255, 255)
setColor ( 0xFFFFFF )
first FF is 00 to FF red component, then goes green, then blue. Read about HTML colors to understand more about this format.
drawing rectangles
------------------
drawFillRect(x,y,width,height)
drawRect(x,y,width,height,linewidth)
random numbers
--------------
randomize()
randomize(seed)
random(range) returns random number (0 inclusive, range exclusive)
randomize()
int a = random(50)
Value of a will be equal from 0 to 49.
fonts and drawing text
----------------------
// font file font size
Font font1 = loadFont ( "test.ttf", 40 )
//test.ttf should be in data folder next to your source file
// xpos ypos Font text color
drawText ( 10, 20, font1, "test text", white )
predefined colors are: white, black, blue, cyan, green, yellow, red, magenta
you can use HTML color format to describe your own color:
drawText ( 10, 20, font1, "test text", 0xAA55ED )
More about strings
------------------
str text2 = "ssss"
creates new string variable
which can be used to draw text on window:
drawText ( 340, 340, testFont, text2 and yellow )
or output to console window
print ( text2 )
printLine ( text2 )
But only for displaying. If you want to use it elsewhre,
you must add .getString() after it:
Next code is valid:
ProlixSound jump
str jumpwavname ( "jump.wav" )
jump is now loadSound ( jumpwavname.getString() )
Next code is INVALID:
ProlixSound jump
str jumpwavname ( "jump.wav" )
jump is now loadSound ( jumpwavname )
You can access individual charactes this way:
text2[5] = 'x'
You can get length of the string this way:
int tl = text2.length()
You can get part of the string this way:
str text2 = text2.substr ( firstcharpos, length )
You can add other string to existing string:
text2 = text2 + "fffff"
text2 = text2 + text3
here is function to replace part of the string:
str text1 = "text to be replaced"
str text2 = "to be"
str text3 = strReplace ( text1, text2, "was" )
here is function to split strings
str gge = "testing split string"
str strl[256]
int cncnt = strSplit ( gge, ' ', strl )
for int ie = 0, ie < cncnt, ie++
print ( strl[ie] )
output will be:
testingsplitstring
to compare strins, use following method:
str a = "test"
str b = "test"
if a.compare(b)==0
//they are identical
if a.compare("test")==0
//identity found again
Image class
-----------
You can use bmps or pngs (with transparency if you want).
Image testimg ( "test.png" )
testimg.draw ( 50, 50 )
for details see definition:
class Image
public:
int w, h //width and height fills automatically after loading image you can access them
void setAlpha (int a) //0-255. you can use opaque and transparent keywords
int getAlpha()
void setPoint( int x, int y, ulong color) //color in HTML format described above
ulong getPoint( int x, int y) //gets color of specified point
void draw( int x, int y)
void draw( int x, int y, int clipx, int clipy, int clipw, int cliph) //draws only part of image.
Image ( str filename) // for non-transparent bmp's and transparent or normal pngs
Image ( str filename, bool isMTransp) // if true, all magenta (0xFF00FF) pixels in bmp will be transparent
//don't use next functions inside loops, i.e. multiple times cause this will eat memory
scale ( float factor ) // 0.5f = x2 downscale, 3 - 3xupscale etc.
rotate ( int degree ) // straight angles rotation: 90, -90, 180, 270 etc.
flipVer ()
flipHor ()
There is also rotateable Image class RImage. It caches all posible rotations in RAM
Example usage:
//loading (after window was created):
RImage tank ( "tank.bmp", true )
//you can only upscale RImage before precaching, not downscale
//use doublescaled sprites in your game to achieve best rotation results with less artifacts
tank.scale ( 2 )
//precache ( precision ). if you use 10 as precision, there will be 36 different angles ( 360/10 )
tank.precache ( 5 ) //less presision gives smoother motion and eats more RAM.
//for small sprites there is no point in values less than 3. small values for small sprites can even show noticeable pixel jerking
...
...
...
//drawing:
//somewhere in the drawing cycle:
tank.draw ( centerX, centerY, degrees ) //it will select cached rotated sprite with nearest degree
//notice, that you pass the center position, not top left corner as with Image class
//another difference from Image is that you can't set Alpha, to draw transparent RImage sprites use:
tank.draw ( centerX, centerY, degrees, alpha ) //where alpha is 0-255
You can't load Image or RImage outside some function or before window was created. But you can use empty constructor:
#include <lsdl>
Image test
RImage rtest
int main()
createWindow ()
test = Image ( "test.bmp" )
rtest = RImage ( "test.bmp" )
rtest.precache ( 10 )
...
Sound class
-----------
class Sound
public:
void play()
void stop()
void play( byte leftvol, byte rightvol, int channel)
void loop( byte leftvol, byte rightvol, int channel)
Sound ( str filename)
you can stop all sounds with command:
stopChannel ( all )
Music
-----
there is no class for music, cause only one music can be played at one time
Music mus1 = loadMusic ( "theme.wav" )
playMusic ( mus1 )
pauseMusic ()
resumeMusic ()
stopMusic ()
Files
-----
fileReader:
.open(), .close(), .readData( var ), .readChar ( char ) or .readByte ( byte )
.get( char* s, 1024 )
.eof() (example: while NOT file3.eof ()
fileWriter:
.open(), .close(), .writeLine( var ), .writeChar ( char ) or .writeByte ( byte )
.write (var)
Or you can use << and >> operators.
Opening:
fileWriter file1 ( "test.txt" )
equals:
fileWriter file1
file1.open ( "test.txt" )
To read whole lines you may use this method:
fileReader tr ( "test2.txt" )
char cline[1024]
tr.getline ( cline, 1024, '\n' )
str line = cline
Save/load example:
------------------
If you're writing simple game, easiest way to store and load data is to use .writeData() and readData()
example:
fileWriter fw ( "sss.txt" )
fw.writeData ( 452 )
fw.writeData ( 91.4f )
fw.close ()
fileReader fr ( "sss.txt" )
int j
float k
fr.readData ( j )
fr.readData ( k )
fr.close ()
printLine ( j )
printLine ( k )
Arrays classes
--------------
xxxArray, xxxArray2D, xxxArray3D,
.get(), .set(indexes to data), .remove(), resize (newsize)
where xxx is byte, int, long, float or double
Multithreading example
----------------------
#include <lsdl>
Thread thread1
Thread thread2
int hello1 is thread function
repeat 20
print ( "hello" )
return 0
int hello2 is thread function
repeat 10
print ( "HELLO" )
return 0
int main()
thread1 = createThread ( hello1, NULL )
thread2 = createThread ( hello2, NULL )
pause ( 1000 )
return 0
Version changes
---------------
version 1.0.9:
- class Bool added. Works like bool, but has members: toggle(), set(), clear()
- Vector2d added. same as Vector2f but with double instead of float
- compilation of utf-8 files now is possible, but is somewhat experimental
- void cp2utf ( char*, char* ) added (cp1251->utf)
version 1.0.8:
- some dlls added to default dll set (mikmod, ogg, vorbis)
- float mod(float). returns absolute value. similar to abs() for integers
- randomDouble(). returns random double from 0 to 1.0
- 139 colors added. enter COLOR_ and ctrl+space in Programmers Notepad to see list of colors
- light_lsdl (withoud ttf, mixer and image functions and dlls) and sample project (pushka)
version 1.0.7:
- void drawCircle ( float x0, float y0, float radius, ulong linecol* )
- void drawCircle ( Vector2f pos, float radius, ulong linecol* )
- void drawFillCircle with same parameters for filled circle. it is raw and slow now, will be optimized in next versions
- void drawLine ( int x1, int y1, int x2, int y2, ulong linecol* )
- void drawLine ( Vector2f start, Vector2f end, ulong linecol* )
- void drawRectangle** ( void drawRectangle ( int x1, int y1, int w, int h, int width=1, ulong linecol** )
- void drawRectangle ( Vector2f cor1, Vector2f cor2, ulong linecol* )
- void drawFillRectangle with same parameters for filled rectangle
* linecol is optional. if not set, color, set by setColor() is used
** drawRect and drawFillRect wasn't touched for backwards compatibility. the difference is - color is described in HTML format and Vector2f can be used to describe two corners of that rectangle
version 1.0.6:
- class Vector2f ( float x, float y ) can be used for storing 2D positions, speeds and directions. has most operators overloaded and methods: void normalize(), float getAngle()*, void moveToAngle ( angle*, speed ) - changes x and y according to the direction angle and speed
- float approxAngle ( float angle*, float targetAngle*, float speed ) - changes angle slowly to match target angle
- code example for some of above desribed functions ( projects\tank )
- float countDist ( Vector2f v1, Vector2f v2 ) and float countDist ( float x1, float y1, float x2, float y2 ) - to find absolute distance between two points (length of the line)
* angle in degrees
version 1.0.5:
- float toRadians ( float degrees ) - converts degrees to radians
- float toDegrees ( float radians ) - vice versa
version 1.0.4:
- RImage class added. Non-aliased raster rotation by any angle, see details in updated README
version 1.0.3:
- Image class updated with new methods: scale(factor), rotate(angle 90/180/270), flipVer(), flipHor()
version 1.0.2:
- png transparency fixed
- Image class updated (w and h members added, empty constructor added)
- Sound class updated (empty constructor added)
- README updated
- unwanted aliases removed
- sstream included in the right place