Lainasin kirjastosta kirjan, Inside Peliohjelmointi. Kirjan mukana tuli Visual C++ 6.0. Nyt on kuitenkin eteen tullut nolo ongelma: en tiedä mistä .lib ja .h tiedostot saadan linkitettyä ohjelmaan. Älkää sanoko "lue ohjeista", sillä en jostain syystä löytänyt muuta kuin juttua MFC:n hienoudesta.
Voisiko joku ystävällisesti kertoa paikan mistä voisi .h ja .lib tiedostoja lisäillä projektiin?
, kiittäen Queq
Visual C++:n juurihakemisto lienee jotain tämän tyylistä:
C:\Program Files\Microsoft Visual Studio\VC98
Se sisältää Include-hakemiston (.h-tiedostot) ja Lib-hakemiston (.lib-tiedostot).
Toisaalta, perus-.h-tiedostoja ei yleensä tarvitse lisäillä muuten kuin esikääntäjän direktiivillä (#include), ja perus-.lib-tiedostot ovat automaagisesti uudessa projektissa mukana.
Mutta eikö jostain kuitenkin pidä määritellä mitkä .lib tiedostot halutaan käyttöön, vai osaako kääntäjä etsiä sen itse..?
Pistä vielä linkitykset <sulkeisiin>, eikä " "
Joo, kiitoksia nyt selvisi. Hämäsi hieman kun Visual C++ toimii aivan erilailla kuin muut käyttämäni kääntäjät.
Eipäs muuten selvinnytkään. Kuvitellaan, että yritän kääntää vaikka Inside Peiohjelmointi kirjan ensimmäisen osan freakout.cpp koodia.
Olen nyt tehnyt muistaakseni näin (en pääse sitä toiselta tietokoneelta tarkistamaan): New File -> New Project > Win32 Aplication > Tyhjä projekti. Saan eteeni tyhjän projektin. Sieltä vasemmasta palkista hiiren kanssa lisään (Add file) lisään freakout.cpp:n. Nyt painan Compile. Eteeni tulee 2 varoitusta, että tiedostossa blacbox.h/cpp on virhe, vaikka siellä virhettä ei olekkaan. Eli teenkö jotain väärin? Edes yksinkertainen helloworld ohjelma ei kääntynyt, vaikka tein juuri näin.
Kysykää jos haluatte tietää jotain mitä yllä olevasta vaikea selkoisesta selvityksestä ei löydy?
No mitkä virheet/varoitukset?
Millasta "Hello World":ä oot kääntämässä? Koodia? Millainen tuo freakout.cpp on? Tarkista tarviiko se jonkun erityisen kirjaston.
No niin, tällä kertaa hello wordi kääntyi, vikana oli ollut inhimillinen virhe edellisellä kerralla. Mutta tuo freakout.cpp ei käänny:
2 erro(s)
e:\oppaat\c++\inside peliohjelmointi\koodit\luku01\blackbox.h(34) error c2146: syntax error missing ';' before identifier 'lpdd'
e:\oppaat\c++\inside peliohjelmointi\koodit\luku01\blackbox.h(34) fatal error c1004: unexpected end of the file found
Tuo blackbox.h on kirjantekijän oma kirjasto, jonka hän otti mukaan ensimmäiseen esimerkkiin. Ja ei opiskelu oikein suju, jos ei edes ensimmäistä esimerkkiä saa käännettyä.
EDI: välilyönti puuttui... :)
Voisin vielä lisätä filut:
// FREAKOUT.CPP - break game demo
// INCLUDES ///////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN // include all macros
#define INITGUID // include all GUIDs
#include <windows.h> // include important windows stuff
#include <windowsx.h>
#include <mmsystem.h>
#include <iostream.h> // include important C/C++ stuff
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <io.h>
#include <fcntl.h>
#include <ddraw.h> // directX includes
#include "blackbox.h" // game library includes
// DEFINES ////////////////////////////////////////////////////
// defines for windows
#define WINDOW_CLASS_NAME "WIN3DCLASS" // class name
#define WINDOW_WIDTH 640 // size of window
#define WINDOW_HEIGHT 480
// states for game loop
#define GAME_STATE_INIT 0
#define GAME_STATE_START_LEVEL 1
#define GAME_STATE_RUN 2
#define GAME_STATE_SHUTDOWN 3
#define GAME_STATE_EXIT 4
// block defines
#define NUM_BLOCK_ROWS 6
#define NUM_BLOCK_COLUMNS 8
#define BLOCK_WIDTH 64
#define BLOCK_HEIGHT 16
#define BLOCK_ORIGIN_X 8
#define BLOCK_ORIGIN_Y 8
#define BLOCK_X_GAP 80
#define BLOCK_Y_GAP 32
// paddle defines
#define PADDLE_START_X (SCREEN_WIDTH/2 - 16)
#define PADDLE_START_Y (SCREEN_HEIGHT - 32);
#define PADDLE_WIDTH 32
#define PADDLE_HEIGHT 8
#define PADDLE_COLOR 191
// ball defines
#define BALL_START_Y (SCREEN_HEIGHT/2)
#define BALL_SIZE 4
// PROTOTYPES /////////////////////////////////////////////////
// game console
int Game_Init(void *parms=NULL);
int Game_Shutdown(void *parms=NULL);
int Game_Main(void *parms=NULL);
// GLOBALS ////////////////////////////////////////////////////
HWND main_window_handle = NULL; // save the window handle
HINSTANCE main_instance = NULL; // save the instance
int game_state = GAME_STATE_INIT; // starting state
int paddle_x = 0, paddle_y = 0; // tracks position of paddle
int ball_x = 0, ball_y = 0; // tracks position of ball
int ball_dx = 0, ball_dy = 0; // velocity of ball
int score = 0; // the score
int level = 1; // the current level
int blocks_hit = 0; // tracks number of blocks hit
// this contains the game grid data
UCHAR blocks[NUM_BLOCK_ROWS][NUM_BLOCK_COLUMNS];
// FUNCTIONS //////////////////////////////////////////////////
LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam)
{
// this is the main message handler of the system
PAINTSTRUCT ps; // used in WM_PAINT
HDC hdc; // handle to a device context
// what is the message
switch(msg)
{
case WM_CREATE:
{
// do initialization stuff here
return(0);
} break;
case WM_PAINT:
{
// start painting
hdc = BeginPaint(hwnd,&ps);
// the window is now validated
// end painting
EndPaint(hwnd,&ps);
return(0);
} break;
case WM_DESTROY:
{
// kill the application
PostQuitMessage(0);
return(0);
} break;
default:break;
} // end switch
// process any messages that we didn't take care of
return (DefWindowProc(hwnd, msg, wparam, lparam));
} // end WinProc
// WINMAIN ////////////////////////////////////////////////////
int WINAPI WinMain( HINSTANCE hinstance,
HINSTANCE hprevinstance,
LPSTR lpcmdline,
int ncmdshow)
{
// this is the winmain function
WNDCLASS winclass; // this will hold the class we create
HWND hwnd; // generic window handle
MSG msg; // generic message
HDC hdc; // generic dc
PAINTSTRUCT ps; // generic paintstruct
// first fill in the window class stucture
winclass.style = CS_DBLCLKS | CS_OWNDC |
CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra = 0;
winclass.cbWndExtra = 0;
winclass.hInstance = hinstance;
winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
// register the window class
if (!RegisterClass(&winclass))
return(0);
// create the window, note the use of WS_POPUP
if (!(hwnd = CreateWindow(WINDOW_CLASS_NAME, // class
"WIN3D Game Console", // title
WS_POPUP | WS_VISIBLE,
0,0, // initial x,y
GetSystemMetrics(SM_CXSCREEN), // intial width
GetSystemMetrics(SM_CYSCREEN), // initial height
NULL, // handle to parent
NULL, // handle to menu
hinstance,// instance
NULL))) // creation parms
return(0);
// hide mouse
ShowCursor(FALSE);
// save the window handle and instance in a global
main_window_handle = hwnd;
main_instance = hinstance;
// perform all game console specific initialization
Game_Init();
// enter main event loop
while(1)
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
// test if this is a quit
if (msg.message == WM_QUIT)
break;
// translate any accelerator keys
TranslateMessage(&msg);
// send the message to the window proc
DispatchMessage(&msg);
} // end if
// main game processing goes here
Game_Main();
} // end while
// shutdown game and release all resources
Game_Shutdown();
// show mouse
ShowCursor(TRUE);
// return to Windows like this
return(msg.wParam);
} // end WinMain
// T3DX GAME PROGRAMMING CONSOLE FUNCTIONS ////////////////////
int Game_Init(void *parms)
{
// this function is where you do all the initialization
// for your game
// return success
return(1);
} // end Game_Init
///////////////////////////////////////////////////////////////
int Game_Shutdown(void *parms)
{
// this function is where you shutdown your game and
// release all resources that you allocated
// return success
return(1);
} // end Game_Shutdown
///////////////////////////////////////////////////////////////
void Init_Blocks(void)
{
// initialize the block field
for (int row=0; row < NUM_BLOCK_ROWS; row++)
for (int col=0; col < NUM_BLOCK_COLUMNS; col++)
blocks[row][col] = row*16+col*3+16;
} // end Init_Blocks
///////////////////////////////////////////////////////////////
void Draw_Blocks(void)
{
// this function draws all the blocks in row major form
int x1 = BLOCK_ORIGIN_X, // used to track current position
y1 = BLOCK_ORIGIN_Y;
// draw all the blocks
for (int row=0; row < NUM_BLOCK_ROWS; row++)
{
// reset column position
x1 = BLOCK_ORIGIN_X;
// draw this row of blocks
for (int col=0; col < NUM_BLOCK_COLUMNS; col++)
{
// draw next block (if there is one)
if (blocks[row][col]!=0)
{
// draw block
Draw_Rectangle(x1-4,y1+4,
x1+BLOCK_WIDTH-4,y1+BLOCK_HEIGHT+4,0);
Draw_Rectangle(x1,y1,x1+BLOCK_WIDTH,
y1+BLOCK_HEIGHT,blocks[row][col]);
} // end if
// advance column position
x1+=BLOCK_X_GAP;
} // end for col
// advance to next row position
y1+=BLOCK_Y_GAP;
} // end for row
} // end Draw_Blocks
///////////////////////////////////////////////////////////////
void Process_Ball(void)
{
// this function tests if the ball has hit a block or the paddle
// if so, the ball is bounced and the block is removed from
// the playfield note: very cheesy collision algorithm :)
// first test for ball block collisions
// the algorithm basically tests the ball against each
// block's bounding box this is inefficient, but easy to
// implement, later we'll see a better way
int x1 = BLOCK_ORIGIN_X, // current rendering position
y1 = BLOCK_ORIGIN_Y;
int ball_cx = ball_x+(BALL_SIZE/2), // computer center of ball
ball_cy = ball_y+(BALL_SIZE/2);
// test of the ball has hit the paddle
if (ball_y > (SCREEN_HEIGHT/2) && ball_dy > 0)
{
// extract leading edge of ball
int x = ball_x+(BALL_SIZE/2);
int y = ball_y+(BALL_SIZE/2);
// test for collision with paddle
if ((x >= paddle_x && x <= paddle_x+PADDLE_WIDTH) &&
(y >= paddle_y && y <= paddle_y+PADDLE_HEIGHT))
{
// reflect ball
ball_dy=-ball_dy;
// push ball out of paddle since it made contact
ball_y+=ball_dy;
// add a little english to ball based on motion of paddle
if (KEY_DOWN(VK_RIGHT))
ball_dx-=(rand()%3);
else
if (KEY_DOWN(VK_LEFT))
ball_dx+=(rand()%3);
else
ball_dx+=(-1+rand()%3);
// test if there are no blocks, if so send a message
// to game loop to start another level
if (blocks_hit >= (NUM_BLOCK_ROWS*NUM_BLOCK_COLUMNS))
{
game_state = GAME_STATE_START_LEVEL;
level++;
} // end if
// make a little noise
MessageBeep(MB_OK);
// return
return;
} // end if
} // end if
// now scan thru all the blocks and see of ball hit blocks
for (int row=0; row < NUM_BLOCK_ROWS; row++)
{
// reset column position
x1 = BLOCK_ORIGIN_X;
// scan this row of blocks
for (int col=0; col < NUM_BLOCK_COLUMNS; col++)
{
// if there is a block here then test it against ball
if (blocks[row][col]!=0)
{
// test ball against bounding box of block
if ((ball_cx > x1) && (ball_cx < x1+BLOCK_WIDTH) &&
(ball_cy > y1) && (ball_cy < y1+BLOCK_HEIGHT))
{
// remove the block
blocks[row][col] = 0;
// increment global block counter, so we know
// when to start another level up
blocks_hit++;
// bounce the ball
ball_dy=-ball_dy;
// add a little english
ball_dx+=(-1+rand()%3);
// make a little noise
MessageBeep(MB_OK);
// add some points
score+=5*(level+(abs(ball_dx)));
// that's it -- no more block
return;
} // end if
} // end if
// advance column position
x1+=BLOCK_X_GAP;
} // end for col
// advance to next row position
y1+=BLOCK_Y_GAP;
} // end for row
} // end Process_Ball
///////////////////////////////////////////////////////////////
int Game_Main(void *parms)
{
// this is the workhorse of your game it will be called
// continuously in real-time this is like main() in C
// all the calls for you game go here!
char buffer[80]; // used to print text
// what state is the game in?
if (game_state == GAME_STATE_INIT)
{
// initialize everything here graphics
DD_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);
// seed the random number generator
// so game is different each play
srand(Start_Clock());
// set the paddle position here to the middle bottom
paddle_x = PADDLE_START_X;
paddle_y = PADDLE_START_Y;
// set ball position and velocity
ball_x = 8+rand()%(SCREEN_WIDTH-16);
ball_y = BALL_START_Y;
ball_dx = -4 + rand()%(8+1);
ball_dy = 6 + rand()%2;
// transition to start level state
game_state = GAME_STATE_START_LEVEL;
} // end if
////////////////////////////////////////////////////////////////
else
if (game_state == GAME_STATE_START_LEVEL)
{
// get a new level ready to run
// initialize the blocks
Init_Blocks();
// reset block counter
blocks_hit = 0;
// transition to run state
game_state = GAME_STATE_RUN;
} // end if
///////////////////////////////////////////////////////////////
else
if (game_state == GAME_STATE_RUN)
{
// start the timing clock
Start_Clock();
// clear drawing surface for the next frame of animation
Draw_Rectangle(0,0,SCREEN_WIDTH-1, SCREEN_HEIGHT-1,200);
// move the paddle
if (KEY_DOWN(VK_RIGHT))
{
// move paddle to right
paddle_x+=8;
// make sure paddle doesn't go off screen
if (paddle_x > (SCREEN_WIDTH-PADDLE_WIDTH))
paddle_x = SCREEN_WIDTH-PADDLE_WIDTH;
} // end if
else
if (KEY_DOWN(VK_LEFT))
{
// move paddle to right
paddle_x-=8;
// make sure paddle doesn't go off screen
if (paddle_x < 0)
paddle_x = 0;
} // end if
// draw blocks
Draw_Blocks();
// move the ball
ball_x+=ball_dx;
ball_y+=ball_dy;
// keep ball on screen, if the ball hits the edge of
// screen then bounce it by reflecting its velocity
if (ball_x > (SCREEN_WIDTH - BALL_SIZE) || ball_x < 0)
{
// reflect x-axis velocity
ball_dx=-ball_dx;
// update position
ball_x+=ball_dx;
} // end if
// now y-axis
if (ball_y < 0)
{
// reflect y-axis velocity
ball_dy=-ball_dy;
// update position
ball_y+=ball_dy;
} // end if
else
// penalize player for missing the ball
if (ball_y > (SCREEN_HEIGHT - BALL_SIZE))
{
// reflect y-axis velocity
ball_dy=-ball_dy;
// update position
ball_y+=ball_dy;
// minus the score
score-=100;
} // end if
// next watch out for ball velocity getting out of hand
if (ball_dx > 8) ball_dx = 8;
else
if (ball_dx < -8) ball_dx = -8;
// test if ball hit any blocks or the paddle
Process_Ball();
// draw the paddle and shadow
Draw_Rectangle(paddle_x-8, paddle_y+8,
paddle_x+PADDLE_WIDTH-8,
paddle_y+PADDLE_HEIGHT+8,0);
Draw_Rectangle(paddle_x, paddle_y,
paddle_x+PADDLE_WIDTH,
paddle_y+PADDLE_HEIGHT,PADDLE_COLOR);
// draw the ball
Draw_Rectangle(ball_x-4, ball_y+4, ball_x+BALL_SIZE-4,
ball_y+BALL_SIZE+4, 0);
Draw_Rectangle(ball_x, ball_y, ball_x+BALL_SIZE,
ball_y+BALL_SIZE, 255);
// draw the info
sprintf(buffer,"F R E A K O U T Score %d Level %d",score,level);
Draw_Text_GDI(buffer, 8,SCREEN_HEIGHT-16, 127);
// flip the surfaces
DD_Flip();
// sync to 33ish fps
Wait_Clock(30);
// check of user is trying to exit
if (KEY_DOWN(VK_ESCAPE))
{
// send message to windows to exit
PostMessage(main_window_handle, WM_DESTROY,0,0);
// set exit state
game_state = GAME_STATE_SHUTDOWN;
} // end if
} // end if
///////////////////////////////////////////////////////////////
else
if (game_state == GAME_STATE_SHUTDOWN)
{
// in this state shut everything down and release resources
DD_Shutdown();
// switch to exit state
game_state = GAME_STATE_EXIT;
} // end if
// return success
return(1);
} // end Game_Main
///////////////////////////////////////////////////////////////// BLACKBOX.H - Header file for demo game engine library
// watch for multiple inclusions
#ifndef BLACKBOX
#define BLACKBOX
// DEFINES ////////////////////////////////////////////////////
// default screen size
#define SCREEN_WIDTH 640 // size of screen
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8 // bits per pixel
#define MAX_COLORS 256 // maximum colors
// MACROS /////////////////////////////////////////////////////
// these read the keyboard asynchronously
#define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// initializes a direct draw struct
#define DD_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
// TYPES //////////////////////////////////////////////////////
// basic unsigned types
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char UCHAR;
typedef unsigned char BYTE;
// EXTERNALS //////////////////////////////////////////////////
extern LPDIRECTDRAW4 lpdd; // dd object
extern LPDIRECTDRAWSURFACE4 lpddsprimary; // dd primary surface
extern LPDIRECTDRAWSURFACE4 lpddsback; // dd back surface
extern LPDIRECTDRAWPALETTE lpddpal; // a pointer to the created dd palette
extern LPDIRECTDRAWCLIPPER lpddclipper; // dd clipper
extern PALETTEENTRY palette[256]; // color palette
extern PALETTEENTRY save_palette[256]; // used to save palettes
extern DDSURFACEDESC2 ddsd; // a direct draw surface description struct
extern DDBLTFX ddbltfx; // used to fill
extern DDSCAPS2 ddscaps; // a direct draw surface capabilities struct
extern HRESULT ddrval; // result back from dd calls
extern DWORD start_clock_count; // used for timing
// these defined the general clipping rectangle
extern int min_clip_x, // clipping rectangle
max_clip_x,
min_clip_y,
max_clip_y;
// these are overwritten globally by DD_Init()
extern int screen_width, // width of screen
screen_height, // height of screen
screen_bpp; // bits per pixel
// PROTOTYPES /////////////////////////////////////////////////
// DirectDraw functions
int DD_Init(int width, int height, int bpp);
int DD_Shutdown(void);
LPDIRECTDRAWCLIPPER DD_Attach_Clipper(LPDIRECTDRAWSURFACE4 lpdds, int num_rects, LPRECT clip_list);
int DD_Flip(void);
int DD_Fill_Surface(LPDIRECTDRAWSURFACE4 lpdds,int color);
// general utility functions
DWORD Start_Clock(void);
DWORD Get_Clock(void);
DWORD Wait_Clock(DWORD count);
// graphics functions
int Draw_Rectangle(int x1, int y1, int x2, int y2, int color,LPDIRECTDRAWSURFACE4 lpdds=lpddsback);
// gdi functions
int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE4 lpdds=lpddsback);
int Draw_Text_GDI(char *text, int x,int y,int color, LPDIRECTDRAWSURFACE4 lpdds=lpddsback);
#endiflainaus:
#include <ddraw.h> // directX includes
Onko sulla DirectX asennettuna?
Pitää asentaa DirectX SDK, joka tulee myös kirjan mukana. Sen jälkeen pitää laittaa kääntäjän hakupolut kohdalleen, eli:
tools > options > directories
sinne pitää lisätä "include files" kohtaan polku directx sdk:n INCLUDE -kansioon, ja "library files" kohtaan polku sdk:n kansioon LIB. ja siirrä ne molemmat nuolien avulla ensimmäiseksi riviksi.
(esim. c:\OHJELMATIEDOSTOT\DIRECTX7A SDK\DXF\INCLUDE)
tämä tarvii tehdä vain kerran, eli kun asentaa sdk:n, mutta seuraava on tehtävä joka projektille:
project > settings > link
"lisää object/library mobules" kohdassa olevan .lib listan perään ne directx-kirjastot joita käytät projektissa
(esim. ddraw.lib)
Eipä toimi vieläkään, mutta ajattelin, että ehkä hieman helpompaakin voisi yrittää kääntää:
http://koti.mbnet.fi/php-m/ongelma/
Kaiken järjen mukaan tässä ei pitäisi lisätä mitään .lib tiedostoja linkkeriin? Voisiko vika olla tietokoneessa? Sillä joskus apachea asentaessani tietokone valitti jotain odbc.dll ja odbc32.dll vikoja ja puuttumisia, ja jostain Visual C++:n valikosta olin näkevinäni nämä tiedostot. Tietokoneestani puuttuu mm. hh.exe joka on windowsin help tiedostojen lukemiseen.
Teitkö nyt siis Win32-console-projektin vai tavallisen Win32-projektin?
"Teitkö nyt siis Win32-console-projektin vai tavallisen Win32-projektin?" Hups, olin tehnyt vahingossa konsoli projektin. No nyt sentään se kääntyi, mutta freakout ei vieläkään...
Ootkos asentanu ne kaikki asetukset DirectX SDKoolle oikein, että mistä löytää kirjastotiedostot esim.
edit:
:-D Ilmeisesti kuvien perusteella ainaki
Kirjan CD:ltäkö DX-SDK:n asensit?
Jos ei siitä muuten olisi liikaa vaivaa, voisin mielelläni ottaa nuo kirjan kaikki esimerkit jos sattuu joskus tarvitsemaan (esim. sähköpostilla, löytyy profiilista).
lainaus:
Kirjan CD:ltäkö DX-SDK:n asensit?
Jos ei siitä muuten olisi liikaa vaivaa, voisin mielelläni ottaa nuo kirjan kaikki esimerkit jos sattuu joskus tarvitsemaan (esim. sähköpostilla, löytyy profiilista).
Ajattelin ladata tiedostot nettiin väliaikaisesti ja lähettää URL tänne, mutta tiedosto olisi 100 MT suuri (MBnet 50 MT rajoitus). Ja sähköpostini tukee vain >2mt tiedostoja...
Ehm.. siis pelkät esimerkit? Miten se nyt niin, vai sisältääkö grafiikatkin?
Esimerkit = Kirjan esimerkki koodit? No, voin yrittää karsia kaikki kuvat yms. jos sellaisia löytyy, mutta tuskin koko siitä paljon pienenee.
Aihe on jo aika vanha, joten et voi enää vastata siihen.