Die Programmiersprache

Eine Programmiersprache wird dazu verwendet, Programme zu erstellen - die spezielle Skriptsprache, über die Sie hier lesen, ist besonders zum Erstellen von Multimedia-Applikationen oder Computerspielen geeignet. Sie ist nicht die einzige Möglichkeit, mit Gamestudio zu arbeiten. Wenn Sie lediglich einfache Spiele wie Shooters 'zusammenklilcken' wollen, läßt sich dies mit Gamestudios Level-Editor WED machen und dann brauchen Sie auch gar nicht weiter zu lesen... wenn Sie aber immer noch hier sind, wollen Sie vermutlich etwas ambitioniertere Projekte programmieren.

Obgleich Sie auch ein externes Entwicklersystem wie VC++® oder Delphi® benutzen können, bekommen Sie mit der Skriptsprache doch schnellere Resultate. Sie ist eine vereinfachte und modernisierte Version der professionellen Sprache C/C++. Während Sie also das Skripten lernen, lernen Sie gleichzeitig die Grundlagen des Computer-Programmierens. Wenn Sie zu anderen modernen Programmiersprachen wie C#, C++, oder Java übergehen wollen, haben Sie mit der Skriptsprache eine hervorragende Einführung. Und das Beste daran ist, daß Sie mit sehr wenig Programmieren sehr viel machen können.

C-Skript war bis 2006 die Standard-Skriptsprache von Gamestudio. Seit 2007 gibt es die Nachfolgersprache lite-C. Sie ist C-Skript äußerst ähnlich - tatsächlich werden Sie auf den ersten Blick gar keinen Unterschied sehen. Auf den zweiten Blick allerdings eröffnet sie jede Menge mehr an Möglichkeiten. Soweit uns bekannt, ist lite-C die einzige Skriptsprache der Welt, die ohne ein externes Entwicklungssystem vollen Zugriff auf Windows API, DirectX und OpenGI-Funktionen ermöglicht. Zu diesem Zweck unterstützt sie nicht einfach nur C-Syntax, sondern auch einige C++ -Features wie Klassen, Methoden und Funktionsüberladung.

Genug der Schwärmerei über das Skripten. Falls Sie noch nie etwas mit Programmieren zu tun hatten, fangen Sie mit dem Skript-Workshop von Gamestudios Downloadseite an. Auch wenn Sie bereits C oder C++ kennen, empfehlen wir trotzdem das Skript-Tutorial, damit Sie die speziellen Features von C-Skript / lite-C im Vergleich zur normalen C-Sprache kennenlernen. Um das C-Programmieren im Detail zu erlernen, finden sich viele Online-Tutorials wie beispielsweise Teach Yourself C in 21 Days (English) oder C von A bis Z (Deutsch).

C-Skript, lite-C, C, C++...

Lite-C kann in zwei Modi verwendet werden: Pure Mode und Legacy Mode. Pure Mode-Code ist einfacher und kürzer. Er benutzt Funktionen der Acknex-Engine und verlangt kein Programmieren von so langweiligem Zeug wie Message-Loops. Im Legacy-Modus sind die Engine-Funktionen nicht verfügbar, so dass Sie alles 'zu Fuß' programmieren müssen, ganz so wie in einem C++-Standard-Entwicklungssystem. Der Code des Legacy-Modus ist jedoch C++ -aufwärtskompatibel - er läßt sich nicht nur mit lite-C kompillieren, sondern ist auch, solange nur Standard-C-Features benutzt werden, mit jedem C++ -Compiler compilierbar.

Feature
C-Script
lite-C Pure
lite-C Legacy
C
C++
Standard -Extension
.wdl
.c
.c
.c
.cpp
Main function
main()
main()
WINAPI WinMain(...)
WINAPI WinMain(...)
WINAPI WinMain(...)

Groß/Kleinschreibung

nein ja ja ja ja
Standard-Variablen
var
var, int, long, short, char, float, double
var, int, long, short, char, float, double
int, long, short, char, float, double

int, long, short, char, float, double

Structs
nur
vordefiniert
ja
ja
ja
ja

Klassen

nein
nur extern
nur extern
nein
ja
Funktions
Überladung
nein
ja
ja
nein
ja
COM / DLL nur Plugins
ja
ja
ja
ja
Windows API nein
ja
ja
ja
ja
Speicherschutz*
ja
ja
nein
nein
nein
Pointerschutz*
ja
ja
nein
nein
nein
Coroutinen** ja ja nein nein nein
Multimedia-Objekte *** ja ja nein nein nein
Kontrollfunktionen if, while if, while, for, do, switch if, while, for, do, switch if, while, for, do, switch if, while, for, do, switch
Code-
Kompilierung
on-the-fly on-the-fly und im Voraus on-the-fly und im Voraus

nur
im Voraus

nur
im Voraus

* Speicherschutz bewahrt Sie davor 'Speicherlücken' zu verursachen, indem allokierte Engineobjekte automatisch deallokiert werden. Pointerschutz erlaubt es, sich nicht um den Unterschied zwischen Pointern und Inhalten kümmern zu müssen.

** Coroutinen sind eine Methode, viele Funktionen gleichzeitig laufen zu lassen (multitasking). Besonders für 3D-Computerspiele wird das gebraucht. C-Skript und lite-C unterstützen dies durch die wait()-Anweisung.

*** Multimedia-Objekte sind vordefinierte Objekte zum Darstellen von Bildern, dem Abspielen von Sounds oder Erstellen von GUI-Elementen und 3D-Objekten.

In den folgenden Abschnitten finden Sie eine Beschreibung der Variablen, Objekte und Funktionen. Features, die ausschliesslich in der Skriptsprache lite-C (also nicht in C-Script) verfügbar sind, sind mit  LC  gekennzeichnet. In Beispielen werden Code-Unterschiede in verschiedenen Farben gekennzeichnet: grün für lite-C und rot für C-Skript. Lite-C ist auf der Gamestudio-Downloadseite frei verfügbar und in der Version A7 der Acknex-Engine enthalten. Wollen Sie ein altes C-Skript in lite-C konvertieren, lesen Sie bitte das Kapitel migration.

Ein kurzer Einblick in etwas Code..

Unten finden Sie zwei Beispiele eines Mandelbrot-Skriptes einmal im Pure- und einmal im Legacy-Modus geschrieben. Wie Sie sehen, besteht das Programm im Pure-Modus fast nur aus Funktionen, die die Mandelbrotfraktale zeichnen. Alles, was nicht mit dem Programmierziel zusammenhängt, wie das Erstellen eines Fensters und die Handhabung einer Mitteilungsschleife, wird automatisch vom Compiler erledigt.

lite-C Pure Mode lite-C Legacy Mode
#include <acknex.h> // Pure Mode
/////////////////////////////////////////////////////// // Draw a Mandelbrot fractal. double m_x = 0.344142, m_y = 0.075094, m_width = 0.017813; long JetColor(double v) { double d = 25.0; v = v/d + 0.5; int i = (int)v; int f = (int)(255*(v-i)); int r=0, g=0, b=0; switch(i) { case 0: r=0; g=0; b=f; break; case 1: r=0; g=f; b=255; break; case 2: r=f; g=255; b=255-f; break; case 3: r=255; g=255-f;b=0; break; case 4: r=255-f;g=0; b=0; break; } return (255<<24)|(r<<16)|(g<<8)|b; } void Draw(BMAP* bmap) { var w = bmap_width(bmap); var h = bmap_height(bmap); var i,j; var times,inset; double x,y,zx,zy,zxs,zys; long detail=100; bmap_lock(bmap); for(i=0;i<w;i++) for(j=0;j<h;j++) { x = m_x+((double)i)*m_width/w; y = m_y+((double)(h-j))*m_width/w; zx = 0; zy = 0; inset = 1; times = 0; while(inset && times<detail) { times++; zxs = zx*zx; zys = zy*zy; zy = 2*zx*zy+y; zx = zxs-zys+x; if (zxs+zys >= 4.0) inset=0; } if(inset) pixel_to_bmap(bmap,i,j,255<<24); else pixel_to_bmap(bmap,i,j,JetColor(times)); } bmap_unlock(bmap); } /////////////////////////////////////////////////////// // Define the panel that carries the image PANEL* mandel_panel = { } // Left mouse button clicked somewhere on the image. // Zoom in by 0.5, calculate a new position, and draw. void mandel_click() { double a; a = mouse_cursor.x/screen_size.x; m_x += m_width*(a-0.5); a = mouse_cursor.y/screen_size.y; m_y += m_width*(0.5-a); m_width *= 0.5; Draw(mandel_panel->bmap); } void main() { // Create a bitmap, screen sized, for the background. mandel_panel.bmap = bmap_createblack(screen_size.x,screen_size.y,8888); // make the panel visible on screen mandel_panel.flags |= SHOW; // don't draw before the D3D device is created wait(1); // Now we can draw Draw(mandel_panel.bmap); // Set a mouse event for redrawing the image on_mouse_left = mandel_click; }
#include <litec.h> // Legacy Mode

//////////////////////////////////////////////////////
// Draw a Mandelbrot fractal. 
double m_x = 0.344142,
  m_y = 0.075094,
  m_width = 0.017813;

long JetColor(double v)
{
   double d = 25.0;
   v = v/d + 0.5;
   int i = (int)v;
   int f = (int)(255*(v-i));
   int r=0, g=0, b=0;

   switch(i) {
     case 0: r=0; g=0; b=f; break;
     case 1: r=0; g=f; b=255; break;
     case 2: r=f; g=255; b=255-f; break;
     case 3: r=255; g=255-f;b=0; break;
     case 4: r=255-f;g=0; b=0; break;
   }
   return r|(g<<8)|(b<<16);
}

void Draw(HDC hdc,long vw,long vh)
{
   long w = vw;
   long h = vh;
   long i,j;
   long times,inset;
   double x,y,zx,zy,zxs,zys;
   long detail=100;
   
   for(i=0;i<w;i++)
   for(j=0;j<h;j++)
   {
     x = m_x+((double)i)*m_width/w;
     y = m_y+((double)(h-j))*m_width/w;
     zx = 0;
     zy = 0;
     inset = 1;
     times = 0;
     while(inset && times<detail)
     {
       times++;
       zxs = zx*zx;
       zys = zy*zy;
       zy = 2*zx*zy+y;
       zx = zxs-zys+x;
       if (zxs+zys >= 4.0) inset=0;
     }
     if(inset)
       SetPixel(hdc,i,j,0);
     else
       SetPixel(hdc,i,j,JetColor(times));
   }
}

/////////////////////////////////////////////////////
// message loop function
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, 
                      WPARAM wParam, LPARAM lParam)
{
   PAINTSTRUCT ps;
   HDC hdc;
   switch(message) {
 
 case WM_LBUTTONDOWN:
// zoom in at cursor position
   {
   RECT rect;
   GetClientRect(hWnd,&rect);
   long x = ((long)lParam)&0xffff;
   long y = (((long)lParam)&0xffff0000)>>16;
   double a;
   a = x; a /= rect.right; m_x += m_width*(a-0.5);
   a = y; a /= rect.bottom; m_y += m_width*(0.5-a);
   m_width *= 0.5;
   InvalidateRect(hWnd,0,0);
   }
   break;

 case WM_DESTROY:
   PostQuitMessage(0);
   break;

 case WM_COMMAND:
   switch(wParam){
   case 1:
   m_x=-2.5;
   m_y=-2;
   m_width=4.0;
   InvalidateRect(hWnd,0,0);
   break;
   case 2:
   break;
   case 3:
   PostMessage(hWnd, WM_CLOSE,0,0);
   break;
   }
   break;

case WM_PAINT:
   hdc = BeginPaint(hWnd, &ps);
   RECT rect;
   GetClientRect(hWnd,&rect);
   Draw(hdc,rect.right,rect.bottom);
   EndPaint(hWnd, &ps);
   break;
   case WM_KEYDOWN:
   switch( wParam )
   {
     case VK_ESCAPE:
     case VK_F12:
     PostMessage(hWnd, WM_CLOSE,0,0);
     break;
   }
   break;

 default:
   return DefWindowProc(hWnd, message, wParam, lParam);
 }
 return 0;
}

int WINAPI WinMain (WINARGS)
{
//Create a window
   char *szClass = "liteCWindowClass";
   HINSTANCE hi = GetModuleHandle(NULL);
   UnregisterClass(szClass,hi);
   WNDCLASSEX wcex;
   wcex.cbSize = sizeof(WNDCLASSEX);
   wcex.style	= CS_HREDRAW|CS_VREDRAW;
   wcex.lpfnWndProc	= WndProc;
   wcex.cbClsExtra	= 0;
   wcex.cbWndExtra	= 0;
   wcex.hInstance	= hi;
   wcex.hIcon	= LoadIcon(hi,(LPCSTR)128);
   wcex.hCursor	= LoadCursor(NULL, IDC_ARROW);
   wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
   wcex.lpszMenuName	= NULL;
   wcex.lpszClassName	= szClass;
wcex.hIconSm = LoadIcon(hi,(LPCSTR)128);
RegisterClassEx(&wcex);
HWND hwnd=CreateWindowEx(0,szClass,
"Mandelbrot",0x96cf0000,0,0,640,480, NULL,0,NULL,NULL);
// create a menu HMENU menu = CreateMenu(); HMENU hSubMenu = CreateMenu(); InsertMenu(hSubMenu,0,MF_BYPOSITION|MF_STRING, 1,"Reset"); InsertMenu(hSubMenu,2,MF_BYPOSITION|MF_STRING, 3,"Quit"); InsertMenu(menu,0,MF_BYPOSITION|MF_STRING|MF_POPUP, (UINT_PTR)hSubMenu,"File"); // activate window, menu, and message loop if (hwnd) { SetMenu(hwnd,menu); ShowWindow(hwnd,SW_SHOW); MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return 0; }

 

► Aktuelle Version Online