ESENTHEL ENGINE SDK 00 - Start.txt /******************************************************************************/ #include "stdafx.h" // include precompiled header #include "resource.h" // include resources (icon) /******************************************************************************/ void InitPre() // init before engine inits { // here you will have to setup initial engine settings // like application name, its options, screen resolution... App.name("Start"); // application name App.icon=(Char*)IDI_ICON1; // setup icon App.flag=APP_NO_FX; // set APP_NO_FX option to tell engine to load only basic drawing methods (no 3d and special effects) PakAdd("../data/engine.pak"); // load engine data } /******************************************************************************/ Bool Init() // init after engine inits { // here when engine will be ready you can load your game data // return false when error occured return true; } /******************************************************************************/ void Shut() // shut at exit { // this is called when the engine is about to exit } /******************************************************************************/ Bool Main() // main updating { // here you have to process each frame update if(Kb.bp(KB_ESC))return false; // exit if escape on the keyboard pressed return true; // continue } /******************************************************************************/ void Draw() // main drawing { // here you have to tell engine what to draw on the screen D.clear(TURQ); // clear screen to turquoise color D.text (0, 0.1,"This is the First Tutorial"); // draw text at (0, 0.1) position D.text (0,-0.1,"Replace the CPP with some other file to view a different Tutorial"); // draw text at (0,-0.1) position } /******************************************************************************/ ESENTHEL ENGINE SDK 01 - Drawing.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Here are presented the most basic drawing functions /******************************************************************************/ void InitPre() { App.name("Drawing"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); // clear to white // draw texts { D.text(0,0,"Default text settings"); // default text draw TextDS tds; // text draw settings, contains information about font size, aligning, color, .. tds.color=BLACK; // set black color tds.scale*=1.4f; // change scale D.text(tds,0,-0.2,"Bigger"); tds.scale/=1.4f; // reset scale tds.align.set(1,0); // change aligning D.text(tds,0,-0.4,"Right Aligned"); tds.color=GREEN; // change color to green tds.align.set(-1,0); // change aligning D.text(tds,0,-0.6,"Colored Left Aligned"); tds.align.set(0,0); // reset aligning tds.color=ColorHue(Tm.time()/3); // assign color to Color Hue according to current time D.text(tds,0,-0.8,"Multi colored"); } // draw shapes { D.rect (BLUE , 0.5,0.5, 0.6,0.6); // draw blue rectangle at given coordinates D.circle(RED , 0.1, -0.5,0.5); // draw red circle with 0.1 radius at (-0.5,0.5) position D.dot (BLACK , 0,0.5); // draw black dot at (0,0.5) position D.line (GREEN , -0.4,0.5, 0.4,0.6); // draw green line D.tri (YELLOW,Vec2(-0.5,-0.4),Vec2(-0.4,-0.2),Vec2(-0.4,-0.4)); // draw yellow triangle from given points } } /******************************************************************************/ ESENTHEL ENGINE SDK 02 - Input.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Vec2 point; // point position Char c; // character pressed /******************************************************************************/ void InitPre() { App.name("Input"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; // here change the default text color Text_ds.shadow=0; // here disable shadows return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Kb.c())c=Kb.c(); // if character pressed remember it to draw it later if(Kb.b(KB_LEFT ))point.x-=Tm.d()/2; // move point left when 'left arrow' is on according to time delta if(Kb.b(KB_RIGHT))point.x+=Tm.d()/2; // move point right when 'right arrow' is on according to time delta if(Kb.b(KB_DOWN ))point.y-=Tm.d()/2; // move point down when 'down arrow' is on according to time delta if(Kb.b(KB_UP ))point.y+=Tm.d()/2; // move point up when 'up arrow' is on according to time delta if(Kb.bp(KB_Z))point.x-=0.1; // when 'z' is pushed , move point left if(Kb.br(KB_X))point.x+=0.1; // when 'x' is released , move point right if(Kb.bd(KB_C))point.y+=0.1; // when 'c' is double clicked, move point up return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.dot(RED ,Ms.pos); // draw red dot at mouse cursor position D.dot(GREEN,point ); // draw green dot at 'point' position if(Ms.b(0))D.dot(BLACK, -0.1,0.4, 0.1); // when 0th mouse button on, draw big black dot if(Ms.b(1))D.dot(BLACK, 0.1,0.4, 0.1); // when 1st mouse button on, draw big black dot D.text(0,0.9, S+"character : "+c ); // draw stored character D.text(0,0.7, S+"mouse : "+Ms.pos); // draw mouse position D.text(0,0.6, S+"point : "+point ); // draw point position } /******************************************************************************/ ESENTHEL ENGINE SDK 03 - Image.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Gfx gfx; // image /******************************************************************************/ void InitPre() { App.name("Image"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { gfx="../data/gfx/particle/star.gfx"; // load image from file return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(BLACK); // draw image gfx.draw(-0.5,0.5, 1,1); // draw at (-0.5,0.5) position with (1,1) size } /******************************************************************************/ ESENTHEL ENGINE SDK 04 - Cache.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("Cache"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(BLACK); Gfxs("../data/gfx/particle/star.gfx")->draw(-0.5,0.5, 1,1); // get image from cache and draw at (-0.5,0.5) position with (1,1) size // for safer use, you can first check if resource exists using 'get' method if(Gfx *gfx=Gfxs.get("non existing image.gfx")) // try to get non existing image, NULL will be returned since image doesn't exist gfx->draw(-0.5,0.5, 1,1); // this won't happen // see what will happen if you wan't to use "non existing image.gfx" when space pressed if(Kb.b(KB_SPACE)) { Gfxs("non existing image.gfx")->draw(-0.5,0.5, 1,1); // when space pushed an error will be shown and application will exit immediately } } /******************************************************************************/ ESENTHEL ENGINE SDK 05 - Gui.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Window window; // gui window Text text ; // gui text Button button; // gui button /******************************************************************************/ void InitPre() { App.name("GUI"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { Gui +=window.create(Rect(-0.5,-0.4,0.5,0.3) ,"Window Title"); // create window and add it to Gui window+=text .create(Vec2(0.5,-0.2f) ,"text" ); // create text and add it to 'window', coordinates are relative to parent (it's top left point) window+=button.create(Rect(0.35f,-0.47f,0.65f,-0.4f),"OK" ); // create button and add it to 'window', coordinates are relative to parent (it's top left point) return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); // update GUI return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); // draw GUI } /******************************************************************************/ ESENTHEL ENGINE SDK 06 - 3D.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("3D"); App.flag=APP_NO_FX|APP_MS_EXCLUSIVE; // setup mouse exclusive mode to hide cursor PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=5; // set initial camera distance to 5 meters return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); // simple camera handle allowing minimum 0.1(10cm) and maximum 10meters zoom, and allowing rotation and zooming return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); Box (1 ).draw(BLACK); // draw black box with 1 meter radius if(Ms.b(0))Ball(1 , Vec(-3,0,0)).draw(BLACK); // when 0th mouse button pushed draw black ball with 1 meter radius and (-3,0,0) position if(Ms.b(1))Tube(0.3,2, Vec( 3,0,0)).draw(BLACK); // when 1st mouse button pushed draw black tube with 0.1 meter radius, 2 meters height and (3,0,0) position } /******************************************************************************/ ESENTHEL ENGINE SDK 07 - Mesh.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mshb mshb; // mesh base (contains vertexes, edges, triangles, quads) /******************************************************************************/ void InitPre() { App.name("Mesh"); App.flag=APP_MS_EXCLUSIVE; // mouse exclusive mode to hide cursor, and APP_NO_FX removed since we'll be using vertex lit Mshb rendering PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=4; mshb.create(Torus(1,0.3),VTX_NRM); // create Mshb from torus, and automatically create vertex normals in order to lit the mshb properly return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); return true; } /******************************************************************************/ void Draw() { D.clear(TURQ); LightDir(Vec(0,0,1)).set(); // set directional light in (0,0,1) direction before rendering to achieve lighting (NOTE: only directional light is supported in simple rendering mode) if(Ms.b(0)) // when left mouse button on { Torus(1,0.3).draw(WHITE,true); // draw flat colored torus through Torus shape }else { mshb.draw(NULL); // draw through Mshb with default material (it will be shaded properly because it has vertex normals) } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Geometry\Camera.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("Camera"); App.flag=APP_NO_FX|APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=5; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; // settings Cam.yaw -=Ms.d.x; // modify yaw according to mouse delta x Cam.pitch+=Ms.d.y; // modify pitch according to mouse delta y Cam.roll +=(Kb.b(KB_Z)-Kb.b(KB_X))*Tm.d(); // modify roll according to Z and X keyboard buttons Cam.dist -=Ms.wheel*0.2; // modify distance according to mouse wheel Clamp(Cam.dist,0.1,10); // clamp distance to minimum and maximum values if(Kb.b(KB_LEFT ))Cam.at-=Cam.matrix.x*Tm.d(); if(Kb.b(KB_RIGHT))Cam.at+=Cam.matrix.x*Tm.d(); if(Kb.b(KB_UP ))Cam.at+=Cam.matrix.y*Tm.d(); if(Kb.b(KB_DOWN ))Cam.at-=Cam.matrix.y*Tm.d(); // camera Cam.setSpherical (Cam.at,Cam.yaw,Cam.pitch,Cam.roll,Cam.dist); // set spherical camera with 'look at' position, angles and distance Cam.updateVelocities( ); // after camera settings are up, we need to update camera velocities in order to achieve correct motion blur when enabled Cam.set ( ); // set as active camera // camera effects if(Kb.bp(KB_SPACE))QuakeFx.addShort(); // add short quake camera effect when space pressed QuakeFx.update (); // update camera effects return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); // draw 4x4 boxes REPD(x,4) REPD(z,4)Box(0.3,Vec(x,0,z)).draw(BLACK); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Geometry\Matrix.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Matrix is a set of values which can be used to determine object's: -position -orientation (rotation) -scale Matrix is built from 4 vectors: -position -x direction (right ) -y direction (up ) -z direction (forward) The default Matrix is called MatrixIdentity, it has its vectors set as following: position(0,0,0) - located at world center, zero position x (1,0,0) - points right y (0,1,0) - points up z (0,0,1) - points forward /******************************************************************************/ void InitPre() { App.name("Matrix"); App.flag=APP_NO_FX|APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=5; Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); return true; } /******************************************************************************/ void Draw(Matrix &matrix) // this function handles optional 'matrix' drawing { if(Kb.b(KB_SPACE)) // draw matrix when space is pressed { SetMatrix(); // reset drawing matrix matrix.pos.draw(GREY,0.02f); // draw matrix position with grey color D.line(RED , matrix.pos, matrix.pos+matrix.x); // draw matrix 'x' (right ) vector with red color D.line(GREEN, matrix.pos, matrix.pos+matrix.y); // draw matrix 'y' (up ) vector with green color D.line(BLUE , matrix.pos, matrix.pos+matrix.z); // draw matrix 'z' (forward) vector with blue color } } void Draw() { D.clear(WHITE); // box { SetMatrix(MatrixIdentity); // set default matrix identity Box(1).draw(BLACK); // draw box at current matrix Draw(MatrixIdentity); // draw matrix } // ball { Matrix m; // matrix (matrix is a position + orientation) m.setPos(Vec(-3,0,0)); // init matrix with initial position SetMatrix(m); // set as active matrix Ball(1).draw(BLACK,false,VecI2(8)); // draw ball at current matrix Draw(m); // draw matrix } // tube { Matrix m; m.setRotateX(Tm.time()); // init matrix with initial x-rotation according to angle from time m.move(Vec(3,0,0)); // move matrix to the right SetMatrix(m); // set as active matrix Tube(0.2,2).draw(BLACK,false,6); // draw tube Draw(m); // draw matrix } D.text(0,0.9,"Press Space to draw Matrixes"); } /****************************************************************************** NOTE : if matrix method starts with 'set' it means it resets matrix and then applies transformation if matrix method doesn't start with 'set' it means it just applies transformation instead of writing: Matrix m; m.setRotateX(Tm.time()); m.move(Vec(3,0,0)); SetMatrix(m); you can write: SetMatrix(Matrix().setRotateX(Tm.time()).move(Vec(3,0,0))); /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\2D Effects.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Gfx logo , // logo image fade ; // fading texture Flt fx_value; // effect value Int fx_index; // effect index /******************************************************************************/ void InitPre() { App.name("2D Effects"); App.flag=APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // import esenthel engine logo logo.Import("../data/logo.png",-1,GFX_2D); // create fading texture fade.create2D(128,128, GFX_L8, 1); if(fade.lock()) { REPD(x,fade.x()) REPD(y,fade.y())fade.pixel(x,y,Random(256)); fade.unlock(); } fade.blur(5,false); // apply gaussian blur with 5 pixel range and no clamping return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; // change effect on key pressed, and reset effect value if(Kb.bp(KB_1)){fx_index=1; fx_value=0;} if(Kb.bp(KB_2)){fx_index=2; fx_value=0;} if(Kb.bp(KB_3)){fx_index=3; fx_value=0;} if(Kb.bp(KB_4)){fx_index=4; fx_value=0;} if(Kb.bp(KB_5)){fx_index=5; fx_value=0;} if(Kb.bp(KB_6)){fx_index=6; fx_value=0;} // increase effect value fx_value+=Tm.d(); return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); if(Kb.b(KB_SPACE))fade.drawFs();else // if space pressed draw fading texture to full screen switch(fx_index) { case 0: { D.text(0,0,"Press 1,2,3,4,5,6 keys to view different effects"); }break; case 1: // Draw Ripple Effect through Gfx::draw() { // set ripple effect values RippleFx ripple; ripple.alpha_add = fx_value; ripple.alpha_scale=-1; // draw image with ripple effect logo.draw(ripple, -1,1,2,2); }break; case 2: // Draw Ripple Effect through helper screen { // draw to helper screen D.fxBegin(true); // start drawing to helper screen logo.draw(-1,1,2,2); // image draw D.fxEnd(); // restore default screen drawing // set ripple effect values RippleFx ripple; ripple.alpha_add = fx_value; ripple.alpha_scale=-1; // draw helper screen with ripple effect ripple.draw(); }break; case 3: // Draw Fade Effect { // draw to helper screen D.fxBegin(true); // start drawing to helper screen logo.draw(-1,1,2,2); // image draw D.fxEnd(); // restore default screen drawing // fade in helper screen with 'fade' fading texture FadeFx(fx_value/2,&fade); }break; case 4: // Titles Effect { // draw to helper screen D.fxBegin(true); // start drawing to helper screen REP(30)D.text(0,D.h()+(Frac(Tm.time())-i)*0.08,"Text Text Text"); // draw text D.fxEnd(); // restore default screen drawing // set effect values TitlesFx titles; // draw helper screen with titles effect titles.draw(); }break; case 5: // Wave Effect { logo.drawFs(); // draw logo on full screen WaveFx(Tm.time()/2,0.8); // apply wave effect onto the full screen }break; case 6: // Radial Blur Effect { logo.drawFs(); // draw logo on full screen RadialBlurFx(Frac(fx_value)*0.3); // apply radial blur effect onto the full screen }break; } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\Color Transformations.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ enum COL_TRANS_MODE // color transformation modes { CT_RGB, CT_RBG, CT_GRB, CT_GBR, CT_BRG, CT_BGR, CT_MONO, CT_HUE, CT_HUE2, CT_CUSTOM, CT_CUSTOM2, }; CChar8 *CTText[]= // color transformation description { "RGB", "RBG", "GRB", "GBR", "BRG", "BGR", "MONO", "HUE", "HUE+", "CUSTOM", "CUSTOM2", }; Gfx gfx ; // Esenthel image Tabs tabs ; // transformation tabs Slider slider; // transformation power/alpha /******************************************************************************/ void InitPre() { App.name("Color Transformations"); PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { gfx.Import("../data/logo.png",-1,GFX_2D,1); Gui+=tabs .create(Rect_U (0,D.h(),D.w()*2,0.06),0,CTText,ELMS(CTText)); Gui+=slider.create(Rect_LU(-D.w(),D.h()-0.1,0.4,0.1)).set(1); slider.color=WHITE; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void ApplyColorTransformation(Int mode) { ColorMatrix cm; // color transformation matrix Flt alpha=slider(); // color transformation power switch(mode) { case CT_RGB : cm.setRGB ( ).draw(alpha); break; case CT_RBG : cm.setRBG ( ).draw(alpha); break; case CT_GRB : cm.setGRB ( ).draw(alpha); break; case CT_GBR : cm.setGBR ( ).draw(alpha); break; case CT_BRG : cm.setBRG ( ).draw(alpha); break; case CT_BGR : cm.setBGR ( ).draw(alpha); break; case CT_MONO: cm.setMono ( ).draw(alpha); break; case CT_HUE : cm.setHue (Tm.time()/4).draw(alpha); break; case CT_HUE2: ColorTransHB(Tm.time()/4,1 ,alpha); break; // use 'ColTransHB' to get correct Hue-Brightness transformation case CT_CUSTOM: { // set custom matrix // dest.r, dest.g, dest.b cm.x .set(1 , 1 , 1 ); // src.r cm.y .set(0 , 0 , 0 ); // src.g cm.z .set(0 , 0 , 0 ); // src.b // add.r , add.g , add.b cm.pos.set(0 , 0.2 , 0 ); // 1 cm.draw(alpha); }break; case CT_CUSTOM2: { // set custom matrix #2 // dest.r, dest.g, dest.b cm.x .set(0.5 , 0.5 , 0.5 ); // src.r cm.y .set(0.5 , 0.5 , 0.5 ); // src.g cm.z .set(0.3 , 0.3 , 1.0 ); // src.b // add.r , add.g , add.b cm.pos.set(0 , 0 , 0 ); // 1 cm.draw(alpha); }break; } } void Draw() { D.clear(); // draw gfx.drawFs(); D.rectShadedX(BLACK,RED , -D.w()/2,-0.7, D.w()/2, -0.75); D.rectShadedX(BLACK,GREEN, -D.w()/2,-0.8, D.w()/2, -0.85); D.rectShadedX(BLACK,BLUE , -D.w()/2,-0.9, D.w()/2, -0.95); // transform colors ApplyColorTransformation(tabs()); // draw gui after transformation Gui.draw(); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\Colors HSB.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("Colors HSB"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); REPD(x,1024) { Flt s0= x /1024.0f , // calculate step0 (fraction) s1=(x+1)/1024.0f , // calculate step1 (fraction) x0=-1+s0*2 , // calculate x0 position x1=-1+s1*2 ; // calculate x1 position UInt c0=ColorHue(s0 ), // calculate color0 from hue value c1=ColorHSB(s0,1,1 ), // calculate color1 from hue saturation brightness value c2=ColorHue(c1,Ms.pos.x); // calculate color2 from color1 modified by hue from mouse x position // draw rectangles with different colors D.rect(c0,x0, 0.1,x1, 0.2); D.rect(c1,x0,-0.1,x1, 0.0); D.rect(c2,x0,-0.3,x1,-0.2); } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\Dynamic Image.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Gfx gfx; // image /******************************************************************************/ void InitPre() { App.name("Dynamic Image"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { gfx.create2D(256,256, GFX_A8R8G8B8, 1); // create 256X256 image, A8R8G8B8 type, 1 mipmap if(gfx.lock()) // in order to edit the texture we must first lock it { FREPD(y,gfx.y()) // iterate through all y's FREPD(x,gfx.x()) // iterate through all x's { gfx.color(x,y, ARGB(255,x,y,0)); // set image (x,y) pixel color to ARGB color } gfx.unlock(); // unlock } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); gfx.draw(-0.5,0.5, 1,1); // draw at (-0.5,0.5) position with (1,1) size } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\Font Make Unicode.txt [Error] - File could not be written... ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\Font Make.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Creating Font is split into few parts: 1. Call 'FontMake' to generate an image on your hard disk, the image will contain all desired characters 2. Optionally you can modify the file on your disk, to customize the font graphics 3. Use 'Font::create' method to create a font from the image Once you have created a Font, you can just save it using 'Font::save', and then in the game load it via 'Font::load' or by using Font cache - 'Fonts' Loading already created font ('Font::load' or 'Fonts') is much faster than creating a font ('Font::create') /******************************************************************************/ Font *font ; // new font Button button; /******************************************************************************/ void InitPre() { App.name("Font Make"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ void CreateFont() { Char *characters=L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!@#$%^&*()[]<>{}`~_-+=;:,.?/|\\'\""; // these are all the basic characters you may want to include in your font // please note that you don't have to worry about accidentally including the same character multiple times, because the engine will only generate 1 copy of a single character // for example you can freely set 'characters' to "0123ABC01" and the engine will generate only "0123ABC" FontMake("Times New Roman",characters,64,0,"LocalData/Times New Roman.png"); // create a image of desired characters created from the font "Times New Roman" located in your "Windows/Fonts" folder, and save it to disk (64 pixel size, 0 weight) // here you may optionally perform some modifications to the image, for example edit the image in external programs // after the image is ready, create the final font from it Font font; if(font.create("LocalData/Times New Roman.png",characters)) // create font from the image and use exactly the same character set 'characters' which were used in the 'FontMake' function font.save ("LocalData/Times New Roman.font" ); // save it, to load it later in your application } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; CreateFont(); // create the new font and save it to disk font=Fonts("LocalData/Times New Roman.font"); // load the font // now let's change Gui's default font for buttons Gui.tds_button.font=font; // assign the new font Gui+=button.create(Rect_C(0,-0.3,0.4,0.1),"Button"); // create a sample button to view the changes return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); TextDS tds; // text draw settings tds.font =font ; // set font parameter to the newly created font tds.color =BLACK; // set black color tds.shadow= 0; // set no shadow D.text( 0,0.2,"This is the default font!"); // draw some text with the default font D.text(tds,0,0 ,"This is the new font!" ); // draw some text with the newly created font, please note the first parameter 'tds' is used to specify the new settings } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\Import Image.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Gfx gfx; // image /******************************************************************************/ void InitPre() { App.name("Importing Images"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { gfx.Import("../data/logo.png",-1,GFX_2D); // import PNG format as a texture return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); gfx.draw(-1,0.5, 2,1); // draw at (-1,0.5) position with (2,1) size } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Graphics\VI - Vertex Index Buffer.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("VI - Vertex Index Buffer"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); // to draw big number of shapes more efficiently please use VertexIndexBuffer (VI) Char8 *mode; if(Kb.b(KB_SPACE)) // when space on, draw in classic mode { REP(10000)D.line (GREEN, 0,0, Cos(i*PI2/10000),Sin(i*PI2/10000)); // draw 10000 lines in classic mode REP(10000)D.rectL(ColorHue(i/10000.),Rect_C(0,0,i/20000.)); // draw 10000 rectangles in classic mode mode="Classic"; }else // draw in buffered mode { // draw lines { VI.color(GREEN); // set green color REP(10000)VI.line (0,0, Cos(i*PI2/10000),Sin(i*PI2/10000)); // draw 10000 lines in buffered mode VI.end (); // finish drawing } //draw rectangles { REP(10000)VI.rectL(ColorHue(i/10000.),Rect_C(0,0,i/20000.)); // draw 10000 lines in buffered mode VI.end (); // finish drawing } mode="Buffered"; } D.text(0,0.9,S+mode+" drawing" ); D.text(0,0.8,S+"Fps: "+Tm.fps()); } /****************************************************************************** NOTE: Each type of drawing must be ended with it's own "end" method // forbidden { REP(10)VI.line(..); REP(10)VI.rect(..); VI.end (); } // good { REP(10)VI.line(..); VI.end (); REP(10)VI.rect(..) VI.end (); } if one drawing method has color parameter and the other doesn't, it means they're different, and separate "end" is needed here as well // forbidden { REP(10)VI.line(RED, x0,y0,x1,y1); REP(10)VI.line( x0,y0,x1,y1); VI.end (); } // good { REP(10)VI.line(RED, x0,y0,x1,y1); VI.end (); VI.color(RED); REP(10)VI.line (x0,y0,x1,y1); VI.end (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\01 - Bars.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Window window ; // gui window SlideBar slidebar; // gui slidebar Progress progress; // gui progressbar Slider slider ; // gui slider /******************************************************************************/ void InitPre() { App.name("Bars"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Gui +=window .create(Rect(-0.5,-0.4,0.5,0.4),"Window with bars"); window+=slidebar.create(Rect(0.1,-0.2,0.9,-0.12)); // create slidebar window+=progress.create(Rect(0.1,-0.4,0.9,-0.32)); // create progressbar window+=slider .create(Rect(0.1,-0.6,0.9,-0.52)); // create slider return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); progress.set(slidebar()); // set progress bar according to slidebar value return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw(); D.text(0,-0.7,S+"SlideBar " +slidebar()); // draw slidebar value D.text(0,-0.8,S+"ProgressBar "+progress()); // draw progressbar value D.text(0,-0.9,S+"Slider " +slider ()); // draw slider value } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\02 - Buttons.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Int value ; // simple integer value Button button_a, // gui button button_b, // gui button button_c; // gui button /******************************************************************************/ void InitPre() { App.name("Buttons"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ void Func(Ptr) // custom function which will be called when button pushed { value++; } Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Gui+=button_a.create(Rect_C(-0.5,0, 0.45,0.08),"Button Func" ,Func); // create button which will call 'Func' function when pushed Gui+=button_b.create(Rect_C( 0.0,0, 0.45,0.08),"Button Manual" ); // create button without any functions, we will handle it manually Gui+=button_c.create(Rect_C( 0.5,0, 0.45,0.08),"Button Stay" ); button_c.mode=BUTTON_STAY; // create button and set a special mode return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); if(button_b())value++; // manually check if button pushed return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); D.text(0,0.6,S+"value = " +value ); // draw 'value' on screen D.text(0,0.5,S+"button_c() = "+button_c()); // draw state of 'button_c' // please note that you can also use automatically called functions with BUTTON_STAY mode // and you can manually check for state change of such button this way: if(button_c.changed())value++; } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\03 - Tabs.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Window window; // gui window Tabs tabs ; // gui tabs Text text ; // gui text Button button; // gui button Image image ; // gui image /******************************************************************************/ void InitPre() { App.name("Tabs"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; CChar8 *tab[]= { "First", "Second", "Third", }; Gui +=window.create(Rect (-0.5,-0.4,0.5,0.4),"Window with tabs"); window+=tabs .create(Rect_LU(0,0,window.crect.w(),0.08),0,tab,ELMS(tab)); // create tabs // add some elements to tabs { tabs.add(0,text .create(Vec2 (window.crect.w()/2,-window.crect.h()/2 ),"Text" )); // create and add text to 0th tab tabs.add(1,button.create(Rect_C(window.crect.w()/2,-window.crect.h()/2,0.4,0.1),"Button" )); // create and add button to 1st tab tabs.add(2,image .create(Rect_C(window.crect.w()/2,-window.crect.h()/2,0.5,0.5),Gfxs("LocalData/image.gfx"))); // create and add image to 2nd tab } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\04 - Window Menu.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Window window; // gui window Menu menu ; // gui menu /******************************************************************************/ void InitPre() { App.name("Window Menu"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ // here are defined functions which are going to be used by menu commands when activated void MenuFileNew (){} void MenuFileOpen(){} void MenuFileSave(){} void MenuFileExit(){StateExit.set();} /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Gui+=window.create(Rect(-0.5,-0.4,0.5,0.4),"Window with menu"); { using namespace MenuDefs; // use this namespace to simplify menu creation // from now on (in current scope) N is a menu node N n; // let's start with main node { N &f=(n+="File"); // add "File" element to main node, and store it's reference in 'f' f.New().create("New" ,MenuFileNew ,KbSc('n',KBSC_CTRL)); // add "New" command to 'f', giving it's procedure and keyboard shortcut (ctrl+n) f.New().create("Open",MenuFileOpen,KbSc('o',KBSC_CTRL)); // add "Open" command to 'f', giving it's procedure and keyboard shortcut (ctrl+o) f.New().create("Save",MenuFileSave,KbSc('s',KBSC_CTRL)); // add "Save" command to 'f', giving it's procedure and keyboard shortcut (ctrl+s) f++; // add empty line f.New().create("Exit",MenuFileExit,KbSc('x',KBSC_CTRL)); // add "Exit" command to 'f', giving it's procedure and keyboard shortcut (ctrl+x) } { N &e=(n+="Edit"); e.New().create("Option",CMENU_TOGGLABLE); // giving CMENU_TOGGLE flag means that we can toggle this element { N &c=(e+="Children"); c+= "child 1"; c.New().create("child 2").desc("This is child 2"); // this element has a description which will be shown when mouse cursor stops on the element c.New().create("child 3",CMENU_TOGGLABLE).setOn(); // this element can be toggled and is checked by default } } window+=menu.create(n); // create menu from nodes and add it to window } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); D .text (0,-0.7,S+"'Option' is "+menu("edit/option")); // draw state of "option" located in "edit" using operator() method // Another way of checking if a command has been selected is to use 'pushed' method, like this: if(menu.pushed("edit/children/child 1")) { // if we're here then "edit/children/child 1" has been selected } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\05 - List.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ struct Struct // custom structure { Flt f; Int i; Byte b; }data[10]= // sample data array { {1.0, 15, 4}, {2.0, 25, 3}, {3.0, 35, 2}, {4.0, 45, 1}, }; ListGroup list_group[]= // gui list group (stores information about structure format) { ListGroup(MEMBER(Struct,f),0.3,L"Float" ), // group describing 'f' member in 'Struct' structure, width of group=0.3, name="Float" ListGroup(MEMBER(Struct,i),0.3,L"Integer"), // group describing 'i' member in 'Struct' structure, width of group=0.3, name="Integer" ListGroup(MEMBER(Struct,b),0.2,L"Byte" ), // group describing 'b' member in 'Struct' structure, width of group=0.2, name="Byte" }; /******************************************************************************/ Window window; // gui window Region region; // gui region List<Struct> list ; // gui list /******************************************************************************/ void InitPre() { App.name("List"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Gui +=window.create(Rect(-0.5,-0.4,0.5,0.4),"Window with list"); window+=region.create(Rect(0.05,-0.6,0.95,-0.1)); // create region region+=list .create(list_group,ELMS(list_group)).setData(data,ELMS(data)); // create list with 'list_group' groups and 'data' data return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); if(Struct *cur=list())D.text(0,-0.7,S+"current element's Integer value "+cur->i); D.text(0,-0.8,S+"current element (on the list) " +list.cur); D.text(0,-0.9,S+"original element (in data) " +list.orderToElm(list.cur)); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\06 - ComboBox.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ ComboBox combobox_a, // combobox combobox_b; // combobox struct ComboBoxElm // combobox element structure { VecI2 vec; }veci2[]= { {VecI2(0, 0)}, {VecI2(0,10)}, {VecI2(0,20)}, {VecI2(1, 0)}, {VecI2(1,10)}, {VecI2(1,20)}, }; CChar* ComboBoxElmFunc(ComboBoxElm &elm) // function which transforms ComboBoxElm into a string { static Str str; return str=S+elm.vec.x+" x "+elm.vec.y; } /******************************************************************************/ void InitPre() { App.name("ComboBox"); App.flag=APP_FULL_TOGGLE|APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // combobox A (from text-only elements) { static CChar8 *elm[]= // combobox elements (must be non-local) { "First", "Second", "Third", }; Gui+=combobox_a.create(Rect_C(-0.5,0, 0.4,0.08),elm,ELMS(elm)); // create combobox with simple elements (text-only) } // combobox B (from custom structure) { ListGroup lg[]= // list groups { ListGroup(ComboBoxElmFunc,0.3,L"Function"), // list group which uses custom function for data interpretation }; Gui+=combobox_b.create(Rect_C(0.5,0, 0.4,0.08)); // create combobox // assign custom elements combobox_b.setGroups(lg ,ELMS(lg ),true) // set list groups .setData (veci2,ELMS(veci2) ); // set list data } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (-0.5, 0.1,S+"combobox_a element: "+combobox_a()); // draw selected element D.text ( 0.5, 0.1,S+"combobox_b element: "+combobox_b()); // draw selected element Gui.draw(); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\07 - Game Menu.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ struct MenuNew // new-game menu { Window window; Text text; Button close; static void Close(Ptr){Mn.window.fadeOut();} void create() { Gui +=window.create(Rect_C(0,0,0.9,0.5)).barVisible(false).hide(); window+=text .create(Vec2 (window.crect.w()/2,-0.15),"New Game"); window+=close .create(Rect_C(window.crect.w()/2,-window.crect.h()/2-0.1,0.4,0.08),"Close",Close); } }Mn; /******************************************************************************/ struct MenuLoad // load-game menu { Window window; Text text; Button close; static void Close(Ptr){Ml.window.fadeOut();} void create() { Gui +=window.create(Rect_C(0,0,0.9,0.5)).barVisible(false).hide(); window+=text .create(Vec2 (window.crect.w()/2,-0.15),"Load Game"); window+=close .create(Rect_C(window.crect.w()/2,-window.crect.h()/2-0.1,0.4,0.08),"Close",Close); } }Ml; /******************************************************************************/ struct MenuOptions // options menu { Window window; Text text; Button close; static void Close(Ptr){Mo.window.fadeOut();} void create() { Gui +=window.create(Rect_C(0,0,0.9,0.5)).barVisible(false).hide(); window+=text .create(Vec2 (window.crect.w()/2,-0.15),"Options"); window+=close .create(Rect_C(window.crect.w()/2,-window.crect.h()/2-0.1,0.4,0.08),"Close",Close); } }Mo; /******************************************************************************/ struct MenuMain // main menu { Window window; Button b_new,b_load,b_options,b_exit; static void New (Ptr){Mn.window.fadeIn();} static void Load (Ptr){Ml.window.fadeIn();} static void Options(Ptr){Mo.window.fadeIn();} static void Exit (Ptr){StateExit.set();} void create() { Gui +=window .create(Rect_C(0,-0.1,0.6,0.6)).barVisible(false); window+=b_new .create(Rect_C(window.crect.w()/2,-0.15,0.4,0.08),"New" ,New); window+=b_load .create(Rect_C(window.crect.w()/2,-0.25,0.4,0.08),"Load" ,Load); window+=b_options.create(Rect_C(window.crect.w()/2,-0.35,0.4,0.08),"Options",Options); window+=b_exit .create(Rect_C(window.crect.w()/2,-0.45,0.4,0.08),"Exit" ,Exit); window.flag&=~WIN_MOVABLE; // disable moving of this window window.level=-1 ; // set lower level so this window will be always below the other created in this tutorial } }Mm; /******************************************************************************/ void InitPre() { App.name("Game Menu"); App.flag=APP_FULL_TOGGLE; // we'll be using GUI effects (window fading) so make sure APP_NO_FX isn't selected PakAdd("../data/engine.pak"); D.mode(800,600).sync(true); } /******************************************************************************/ Bool Init() { // in games disable highlighting elements with keyboard focus Gui.kb_lit=0; // change default gui text colors Gui.tds_text.color=WHITE; Gui.tds_text.shadow=255; // change Default Gui Window Style Gui.style_window.gfx_back =Gfxs("../data/Gui/Style/0/back.gfx"); Gui.style_window.gfx_border =Gfxs("../data/Gui/Style/0/border.gfx"); Gui.style_window.border_color=WHITE; Gui.style_window.back_color =BLUE; Gui.style_window.border_width=0.03; Mn.create(); Ml.create(); Mo.create(); Mm.create(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(); Gui.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\08 - Loading Gui Objects.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Instead of creating all Gui Objects manually in the code, you can create them in the Gui Editor tool, and then just load them. /******************************************************************************/ GuiObjs gui_objs; TextLine *name; Button *next; /******************************************************************************/ void InitPre() { App.name("Loading Gui Objects"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).sync(true); } /******************************************************************************/ void ButtonFunction(Ptr) // custom function called when button pressed { if(name)name->clear(); // if we have accessed the 'name' TextLine then simply clear it } /******************************************************************************/ Bool Init() { Gui.kb_lit=0; // load prepared Gui Objects in Gui Editor if(gui_objs.load("gui/obj/player name.gobj")) { // if loaded succesfully 'gui_objs' now contains all the buttons, windows and other objects, stored in containers // first we'll add all of them to the Gui (more specifically to the active desktop) : Gui+=gui_objs; // now all objects are placed onto the desktop // the next step is to access the objects, accessing is done by requesting objects by name // each objects name has to be manually set in the Gui Editor name=gui_objs.getTextLine("name"); // get the 'player name' TextLine, which has its name set to "name" (it has been set in the Gui Editor) next=gui_objs.getButton ("next"); // get the 'next' Button , which has its name set to "next" (it has been set in the Gui Editor) next->func=ButtonFunction; // once we have the button we can manually assign a function for it, which will be called when the button is pressed return true; } return false; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(); Gui.draw (); if(name)D.text(0,0.9,S+(*name)()); // draw accessed TextLine value } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\09 - Extending Gui Objects.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Because the main methods of Gui Objects are virtual, you can extend them. /******************************************************************************/ struct Button2 : Button // Create a new class extending the default Gui Button { virtual void test (GuiPC &gpc); // extend testing if object is under mouse cursor virtual Button2& update(GuiPC &gpc); // extend updating object virtual void draw (GuiPC &gpc); // extend drawing object }; void Button2::test(GuiPC &gpc) // extend testing { __super::test(gpc); // call default method } Button2& Button2::update(GuiPC &gpc) // extend updating { __super::update(gpc); // call default method return T; // return self } void Button2::draw(GuiPC &gpc) // extend drawing { D.clip(gpc.clip); // clip display drawing to given clipping rectangle, this is needed for example when object is inside a window, and is partially hidden because the parent's rectangle doesn't fully cover this object UInt color=(visuallyPushed() ? BLACK : ColorLerp(RED_DARK,RED,lit())); // set different color depending if the button is pushed and highlighted D.rect(color, rect+gpc.offset); // draw a background rectangle, moved by 'gpc.offset' (parents offset) D.text(rect.center()+gpc.offset, text); // draw button's text, at center of rectangle and again moved by 'gpc.offset' } /******************************************************************************/ Button2 button; // create a sample button /******************************************************************************/ void InitPre() { App.name("Extending Gui Objects"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).sync(true); } /******************************************************************************/ Bool Init() { Gui+=button.create(Rect_C(0,0,0.5,0.1),"New Button"); // add the button to the active desktop return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\10 - Extending and Loading Gui Objects.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ // Define extended version of default 'Button' /******************************************************************************/ struct Button2 : Button { virtual void test (GuiPC &gpc); virtual Button2& update(GuiPC &gpc); virtual void draw (GuiPC &gpc); }; void Button2::test(GuiPC &gpc) { __super::test(gpc); } Button2& Button2::update(GuiPC &gpc) { __super::update(gpc); return T; } void Button2::draw(GuiPC &gpc) { D.clip(gpc.clip); UInt color=(visuallyPushed() ? BLACK : ColorLerp(RED_DARK,RED,lit())); D.rect(color, rect+gpc.offset); D.text(rect.center()+gpc.offset, text); } /******************************************************************************/ GuiObjs gui_objs; Button2 button; /******************************************************************************/ void InitPre() { App.name("Extending and Loading Gui Objects"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).sync(true); } /******************************************************************************/ Bool Init() { Gui.kb_lit=0; // replace default 'Button' class with extended 'Button2' gui_objs.replaceButton<Button2>(); // load the gui objects if(gui_objs.load("gui/obj/player name.gobj")) { Gui+=gui_objs; return true; } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(BLACK); Gui.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\11 - Multiple Viewports.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** In this tutorial we'll present multiple viewports with different cameras, We'll use 'GViewport::user' to set camera's index /******************************************************************************/ GViewport viewport[2]; Camera camera [2]; /******************************************************************************/ void Render(GViewport &viewport) // rendering function wich will be called when drawing the Gui Viewport element { Int camera_index=Mid(viewport.userd,0,ELMS(camera)-1); // get camera index and clamp it for safety, in case the user data is invalid // activate camera camera[camera_index].set(); // simple rendering D.clear(BLACK); Box(1,Vec(0,0,0)).draw(WHITE); } /******************************************************************************/ void InitPre() { App.name("Multiple Viewports"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).sync(true); } /******************************************************************************/ Bool Init() { // initialize cameras camera[0].setSpherical(Vec(0,0,0),0,0,0,3); camera[1].setSpherical(Vec(0,0,0),0,0,0,3); Gui+=viewport[0].create(Rect_C(-0.5,0,0.9,0.9),Render,(Ptr)0); // create a viewport with 'user=0' to mark camera[0] usage Gui+=viewport[1].create(Rect_C( 0.5,0,0.9,0.9),Render,(Ptr)1); // create a viewport with 'user=1' to mark camera[1] usage return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); // now we'll modify camera angles and distance // first we'll detect which camera to update { Camera *cam=NULL; // start with none // 'Gui.viewport' specifies current Gui Viewport under mouse cursor if(Gui.viewport==&viewport[0])cam=&camera[0];else if(Gui.viewport==&viewport[1])cam=&camera[1]; if(cam) // if found a camera { // modify camera values by mouse movement if(Ms.b(0)) // only when mouse button pressed { cam->yaw -=Ms.d.x; cam->pitch+=Ms.d.y; } // modify camera distance by mouse wheel if(Ms.wheel<0)cam->dist*=1.2; if(Ms.wheel>0)cam->dist/=1.2; cam->setSpherical(); // apply changes by calling 'setSpherical' which sets camera matrix from current values } } // update all camera velocities, this is needed when using Motion Blur effect REPA(camera)camera[i].updateVelocities(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw ( ); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Gui\12 - Window IO.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ WindowIO wio_mesh; // window handling input/ouput Mesh mesh ; // mesh which will be used for saving,loadng and drawing /******************************************************************************/ void InitPre() { App.name("Window IO"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).sync(true); } /******************************************************************************/ void Load(CChar *name) // this function will be called when WindowIO will load a file { mesh.load(name); } void Save(CChar *name) // this function will be called when WindowIO will save a file { // here you can save your file, however in this tutorial we're not going to do this // mesh.save(name); } /******************************************************************************/ Bool Init() { wio_mesh.create("mesh",CNULL,IOPath(),Load,Save); // create a WindowIO, giving accepted file extension, paths, and IO functions wio_mesh.path_mode=WIN_IOP_PART; // set displaying path mode on the window title bar return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); wio_mesh.update(); // WindowIO needs to be manually updated // activate saving/loading on keypress if(Kb.bp(KB_F2))wio_mesh.save(); if(Kb.bp(KB_F3))wio_mesh.load(); return true; } /******************************************************************************/ void Draw() { D .clear(GREY); Cam .setSpherical(Vec(0),Tm.time(),0,0,mesh.box.size().length()*1.2).updateVelocities().set(); LightDir(Cam.matrix.z).set(); mesh.draw(MatrixIdentity); D .text(0,0.9,"Press F2/F3 to save/load"); Gui .draw(); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Calculator.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ TextLine textline; // Gui TextLine /******************************************************************************/ void InitPre() { App.name("Calculator"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Gui+=textline.create(Rect(-0.5,0,0.5,0.1)); // add textline to gui desktop textline.kbSet(); // set keyboard focus return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); D.text(0,-0.4,S+CalcR(textline())); // draw calculated value from 'textline' as Real } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Config.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("Config"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); // here you can set initial settings // they will be used in case "config.txt" file is not found or incomplete // .. if(ConfigLoad()) // here settings are loaded from "config.txt" { // if settings were loaded properly, you can optionally override them here // .. } } /******************************************************************************/ Bool Init() { return true; } /******************************************************************************/ void Shut() { ConfigSave(); // here settings are saved to "config.txt" } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Cpu.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Str s; /******************************************************************************/ void InitPre() { App.name("CPU"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // check which features are supported if(Cpu.flag()&CPU_MMX )s.space()+="MMX"; if(Cpu.flag()&CPU_3DNOW )s.space()+="3dNow"; if(Cpu.flag()&CPU_3DNOW2)s.space()+="3dNow+"; if(Cpu.flag()&CPU_SSE )s.space()+="SSE"; if(Cpu.flag()&CPU_SSE2 )s.space()+="SSE2"; if(Cpu.flag()&CPU_SSE3 )s.space()+="SSE3"; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0.3,S+"Number of cores: " +Cpu.cores()); D.text (0,0.1,S+"Supported features: "+s); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Drag & Drop.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Memb<Char[MAX_PATH]> names; /******************************************************************************/ void Drop() { names.clear(); // remove all existing elements in container for(;CChar *name=DropName();) // iterate through all files dropped { // here you can perform operations on dropped file, by accessing it's 'name' // in this tutorial we will just store the name in a memory container Set(names.New(),name); // copy 'name' to 'names' container } } /******************************************************************************/ void InitPre() { App.name("Drag & Drop"); App.flag=APP_NO_FX; App.drop=Drop; // enable Drag & Drop by specifying function called when a file will be dropped on window PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0.9,"Drag & Drop some files to this window"); FREPA(names)D.text(0,0.7-i*0.1,names[i]); // draw all file names } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\File.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Files are universal and can be used to: -read/write from stdio files (typical files on you Hard Drive) -read files from Pak (an archive of multiple files) They handle encrypting/decrypting with given Secure key /******************************************************************************/ struct Data { Char text[256]; }; /******************************************************************************/ void InitPre() { App.name("File"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Data data; Set(data.text,"Sample text"); // for testing we'll start with with writing to a file in memory { File f; // file object f.writeMem( ); // start writing to memory (file will automatically handle the memory allocations) f.putByte ( 128); // put Byte '128' to file f.putDwrd (0x12345678); // put U32 '0x12345678' to file f<<data; // put 'data' to file (it's raw memory) } // now let's write all that to a real file on Hard Disk { File f; f.write ("LocalData/file.dat"); // start writing to file f.putByte( 128); f.putDwrd(0x12345678); f<<data; } // when the file is created we can now read it { File f; f.read ("LocalData/file.dat"); // start reading file Byte b=f.getByte(); // read Byt (returns 128) UInt d=f.getDwrd(); // read U32 (returns 0x12345678) f>>data ; // read 'data' (data.text should be "Sample text") } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\FileFind.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Memb<Char[MAX_PATH]> names; /******************************************************************************/ void InitPre() { App.name("FileFind"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ void AddName(CChar *name) // add 'name' to names list { Set(names.New(),name); // create new element in names and set it's name } void ManualFind(Str path) // manually iterate through directories and files { for(FileFind ff(path); ff();)switch(ff.type) // start looking for files in path, continue while active, and check for encountered type { case FSTD_DIR : ManualFind(ff.pathName()); break; // if directory encountered start looking inside it case FSTD_FILE: AddName (ff.pathName()); break; // if file encountered add it to the list } } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Kb.bp(KB_SPACE)) { names.clear(); // clear elements FAll("source",AddName); // use FAll which operates on all files inside given path (AddName will be called multiple times with each file name as a parameter) } if(Kb.bp(KB_ENTER)) { names.clear(); // clear elements ManualFind("source"); // manually iterate through all directories and files } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0.9,"Press Space to use FAll, or press Enter for FileFind"); FREPA(names)D.text(0,0.8-i*0.1,names[i]); // draw all file names } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\FileText.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** FileText is meant for operations performed on a text file /******************************************************************************/ struct Data // custom Data structure to test text file saving/loading { Flt volume; Int graphics_mode; Char player_name[64]; Bool saveTxt(Str name); // save data to text file Bool loadTxt(Str name); // load data from text file }; /******************************************************************************/ Bool Data::saveTxt(Str name) { FileText f; // FileText object if(f.write(name)) // if file opened successfully { f.put ("Volume = ",volume ); f.put ("GraphicsMode = ",graphics_mode); // please note "GraphicsMode" is used instead of "Graphics Mode" (names are required to don't have spaces) f.putName("PlayerName = ",player_name ); // FileText::putName will automatically put the value in quotes return true; // return success } return false; // return failure } Bool Data::loadTxt(Str name) { // set default values to members in case file not found or file incomplete volume=1; graphics_mode=5; player_name[0]=0; FileText f; if(f.read(name)) // if file opened successfully { for(;f.level();) // process file within its level { if(f.cur("Volume" ))volume =Sat(f.getReal() );else // if encountered "Volume" then read a floating point value, saturate it and store into 'value' if(f.cur("GraphicsMode"))graphics_mode=Mid(f.getInt (),0,10);else // if encountered "GraphicsMode" then read a integer value, clamp it and store into 'graphics_mode' if(f.cur("PlayerName" ))Set(player_name, f.getName() ); // if encountered "PlayerName" then read a string using 'FileText::getName' method into 'player_name' } return true; // return success } return false; // return failure } /******************************************************************************/ void InitPre() { App.name("FileText"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // set sample data values Data data; data.volume =0.5; data.graphics_mode=2; Set(data.player_name,"He-Man"); data.saveTxt("LocalData/file.txt"); // save data to text file data.loadTxt("LocalData/file.txt"); // load data from text file OSLaunch("LocalData/file.txt"); // open the text file in default Windows viewer to check what actually has been saved return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\IO Path.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** To work easily with relative path's 'IOPath' is used when IOPath is set it is treated as additional path for your files/resources For Example you have all your data stored in 'd:/game/data', like: 'd:/game/data/gfx/..' 'd:/game/data/anim/..' 'd:/game/data/obj/..' and you'd like to access them more simply: "gfx/.." "anim/.." "obj/.." To do so, all you have to do is set IOPath to "d:/game/data" /******************************************************************************/ Gfx *gfx; /******************************************************************************/ void InitPre() { App.name("IO Path"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // in this sample we'll load "image.gfx" which is located in "LocalData" folder where the tutorials are ("LocalData/image.gfx") IOPath("LocalData"); // setup additional IO Search Path gfx=Gfxs("image.gfx"); // load image, IOPath will be used automatically return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); gfx->draw(-0.5,0.5, 1,1); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Memory.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ struct Data // custom data structure { Byte bytes[100]; Int integer; Flt value; }; /******************************************************************************/ // memory containers Memb<Data> memb; // block based Meml<Data> meml; // list based /******************************************************************************/ void InitPre() { App.name("Memory"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // adding elements { // Memb { Data &data=memb.New(); data.integer=5; } // Meml { Data &data=meml.New(); data.integer=5; } } // iterating through all elements { // Memb for(Int i=0; i<memb.elms(); i++) { Data &d=memb[i]; } // Memb through better macro FREPA(memb) { Data &d=memb[i]; } // Meml for(MemlNode *i=meml.first; i; i=i->next) { Data &d=meml[i]; } // Meml through macro MFREP(meml) // please note that here 'i' is not an 'Int' but a 'MemlNode*' { Data &d=meml[i]; } } // removing elements { // Memb { memb.remove(0,true); // remove 0th element, second parameter determines keeping order (read more in the header) } // Meml { meml.remove(meml.first); } } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Mouse Cursor.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("Mouse Cursor"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Kb.bp(KB_1))Ms.cursor(Gfxs("../data/gfx/cursor/0.gfx")); // if '1' pressed change cursor to '0.gfx' if(Kb.bp(KB_2))Ms.cursor(Gfxs("../data/gfx/cursor/1.gfx")); // if '2' pressed change cursor to '1.gfx' return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0,"Press '1' or '2' to change mouse cursor"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Number.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Number is a number able to store very big values with big precision (Int or Real) /******************************************************************************/ Number n0,n1,n2,n3,n4; /******************************************************************************/ void InitPre() { App.name("Number"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // assign 1.0 n0=1.0; // do some big operations n0*=100000; n0.sqrt(); n0+=123.456; n0*=100000; n0.sqrt(); n0+=123.456; n0*=100000; n0.sqrt(); n0+=123.456; // revert operations n0-=123.456; n0.sqr(); n0/=100000; n0-=123.456; n0.sqr(); n0/=100000; n0-=123.456; n0.sqr(); n0/=100000; // n0 should be back to 1.0 // calculate sqrt(sqrt(sqrt(1000000000000000000000000000000.))) n1=Str("1000000000000000000000000000000."); n1.sqrt(); n1.sqrt(); n1.sqrt(); // NOTE: Number can be internally an Int or Real (check Number::real) // any operation between Int and Int results also in Int (any other in Real) // when calculating Number(10)/3 you'll get 3 instead of 3.333.. // to convert Number to be Int or Real use toInt() and toReal() methods { n2=Number(10 )/3; // Int /Int = Int (3) n3=Number(10.0)/3; // Real/Int = Real (3.333..) n4=10; // Int n4.toReal(); // convert to Real n4/=3; // Real/Int = Real (3.333..) } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0.6, S+"n0 = "+n0.asReal()); D.text (0,0.4, S+"n1 = "+n1.asReal()); D.text (0,0.2, S+"n2 = "+n2.asReal()); D.text (0,0.1, S+"n3 = "+n3.asReal()); D.text (0,0.0, S+"n4 = "+n4.asReal()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Pak Create.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Byte b1,b2; // bytes /******************************************************************************/ void InitPre() { App.name("Pak Create"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // create Pak from one file/directory { PakCreate("LocalData"); // create Pak from "LocalData" folder, if no 'pak_name' is specified it will be automatically set (in this case it'll be "LocalData.pak") } // create Pak from list of files { Memb<Char[MAX_PATH]> list; Set(list.New(),"LocalData" ); // add "LocalData" directory to the list Set(list.New(),"stdafx.h" ); // add "stdafx.h" file to the list Set(list.New(),"stdafx.cpp"); // add "stdafx.cpp" file to the list PakCreate(list); // create Pak from list, 'pak_name' will be automatically set to "Tutorials.pak" } // create Pak from files in memory { Memb<File> file; // array of file's which we'll create and write to them using namespace PakDefs; // use this namespace to simplify Pak creation // from now on in current scope: // N is a file node Node<PakNode> N n; // lets start with main node { File &f=file.New(); // add new file to array f.writeMem(); // start writing to memory f.putByte(123); // write a Byte to that file n.New().set("File 1.dat",f); // add this file to file nodes } { N &d=(n+="Directory"); // add new directory { File &f=file.New(); // add new file to array f.writeMem(); // start writing to memory f.putByte(234); // write a Byte to that file d.New().set("File 2.dat",f); // add this file to directory } } PakCreate(n,"Pak from memory.pak"); // create Pak from nodes } // load custom Pak { PakAdd("Pak from memory.pak"); // from now on any data stored in loaded Pak can be accessed through IO methods { File f1("File 1.dat"); // open the file b1=f1.getByte(); // read Byte from that file File f2("Directory/File 2.dat"); // open the file b2=f2.getByte(); // read Byte from that file } } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0,S+b1+" "+b2); // display bytes } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Pak.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Pak is a storage file type, it contains multiple files inside. Once you load a Pak you can access all the files inside it. /******************************************************************************/ Gfx *gfx; /******************************************************************************/ void InitPre() { App.name("Pak's"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // 'sample.pak' used in this tutorial has only one folder 'folder' and one file 'image.gfx' located in 'folder' like this: // "folder/image.gfx" // load custom Pak PakAdd("../data/sample.pak"); // from now on any data stored in loaded Pak can be accessed through IO methods { // you can open files stored in that Pak: { File f; f.read ("folder/image.gfx"); // start reading file f.getByte( ); // get Byte from that file } // you can access resources through cache { gfx=Gfxs("folder/image.gfx"); } } // Pak's can be easily made using "Converter.exe" located in "Tools" folder return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); gfx->draw(-0.5,0.5, 1,1); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Pathfind.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ PathFind pf ; // path finder Memb<VecI2> path ; // path VecI2 start,end; // start and end position of wanted path /******************************************************************************/ void InitPre() { App.name("Pathfind"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Gfx map; if( map.ImportTry("../data/gfx/map/map.png",-1,GFX_SOFT)) { pf.create(map.x(),map.y()); REPD(y,pf.y()) REPD(x,pf.x()) { UInt color=map.color(x,y); // get pixel color of loaded map pf.pixelFlag(x,y,(color!=BLACK) ? PFP_WALKABLE : 0); // set non black color for walkable pixels } } return true; } void Shut() { } /******************************************************************************/ VecI2 ScreenToPix(Vec2 &screen) { Int size=Max(pf.x(),pf.y())*4/3; return VecI2(Round((screen.x+D.h()*3/4)*size/2), Round((screen.y+D.h()*3/4)*size/2)); } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; // set starting position on LMB if(Ms.b(0)) { start=ScreenToPix(Ms.pos); pf.find(start,path); } // set ending position on RMB if(Ms.b(1)) { end=ScreenToPix(Ms.pos); pf.setTarget(end.x,end.y).find(start,path); } return true; } /******************************************************************************/ void DrawPixel(Int x,Int y,UInt color) { Int size=Max(pf.x(),pf.y())*4/3; VI.dot(color, Vec2(x,y)*2/size-D.h()*3/4, 1.0f/size); } void Draw() { D.clear(GREY); REPD(y,pf.y()) REPD(x,pf.x())DrawPixel(x,y,FlagTest(pf.pixelFlag(x,y),PFP_WALKABLE) ? WHITE : BLACK); // draw map REPA(path )DrawPixel(path[i].x,path[i].y,YELLOW); // draw path with yellow color DrawPixel(start .x,start .y,GREEN ); // draw starting position with green color DrawPixel(end .x,end .y,RED ); // draw ending position with red color VI.end(); D.text(0,0.9,"Press LMB and RMB to set Start and End position"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Random.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("Random"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); // enable screen synchronization } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Cam .dist =2; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC ))return false; if(Kb.b (KB_SPACE))CamHandle(0.1,10,CAMH_ZOOM|CAMH_ROT); return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); if(Kb.b(KB_SPACE)) // when space on draw random points in 3D { // here we're rendering 10 000 dots, such big number is more efficient to draw through VertexIndexBuffer (for more information about it check its tutorial in "advanced\graphics") VI.color(ColorAlpha(TURQ,0.1)); // set color REP(10000)VI.dot (Random(Capsule(0.5,2))); // draw dot at random position in capsule VI.end (); // finish buffered drawing }else { D.text(0,0.7,S+Random(4)+" "+Random(10,15)+" "+RandomF()+" "+RandomF(10,15)); REP(1000)D.dot(BLUE,Random(Circle(0.5 ))); // draw 1000 random points inside circle REP(1000)D.dot(RED ,Random(Rect (0.5,-0.5,1,0.5))); // draw 1000 random points inside rectangle } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Sort.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Flt floats[8]; struct CustomData { Byte bytes[100]; Flt real; Int integer; }data[8]; Memb<CustomData> memb; /****************************************************************************** Custom comparing functions must be of "Int name(TYPE &a,TYPE &b)" format they receive references to 2 custom data elements they must return: -1 if 'a' should be before 'b' +1 if 'a' should be after 'b' 0 if 'a' is the same as 'b' /******************************************************************************/ Int CompareCustomData(CustomData &a,CustomData &b) { if(a.real<b.real)return -1; if(a.real>b.real)return +1; return 0; } /******************************************************************************/ void InitPre() { App.name("Sorting"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; REPA(floats)floats[i] =RandomF(10); // fill 'floats' with random values (0..10) REPA(data )data [i].real=RandomF(10); // fill 'data.real' with random values (0..10) REP (8 )memb (i).real=RandomF(10); // fill 'memb.real' with random values (0..10) return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Kb.bp(KB_SPACE)) // sort when space pressed { Sort(floats,ELMS(floats) ); // sort 'floats' Sort(data ,ELMS(data ),CompareCustomData); // sort custom data by giving pointer to data, number of elements and custom comparing function Sort(memb ,CompareCustomData); // sort custom data by giving memory block and custom comparing function } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0,0.7,"Press Space to sort"); Str s="floats: "; FREPA(floats){s+=floats[i] ; s+=" ";} D.text(0, 0.2,s); // draw 'floats' in one string s="data: " ; FREPA(data ){s+=data [i].real; s+=" ";} D.text(0, 0.0,s); // draw 'data.real' in one string s="memb: " ; FREPA(memb ){s+=memb [i].real; s+=" ";} D.text(0,-0.2,s); // draw 'memb.real' in one string } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\States.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** States are used for different 'Application States' for example there can be 'intro state', 'menu state', 'game state' /******************************************************************************/ extern State StateMenu,StateIntro,StateGame; // forward declare used states in this tutorial /******************************************************************************/ void InitPre() { App.name("States"); PakAdd("../data/engine.pak"); } Bool Init() { StateIntro.set(); // set StateIntro as the active state, this means that from now on, only StateIntro's update and drawing methods will be called instead of 'Main' and 'Draw' return true; } void Shut() { } Bool Main(){return true;} void Draw(){} /******************************************************************************/ // INTRO /******************************************************************************/ Bool InitIntro(){return true;} void ShutIntro(){} Bool UpdateIntro() { if(StateActive->time()>3 || Kb.bp(KB_ESC)) // if active state (which here is StateIntro) is running for more than 3 seconds or escape pressed StateMenu.set(1.0); // then switch to 'StateMenu' state with 1.0 second smooth fading return true; } void DrawIntro() { D.clear(BLACK); D.text (0,0,"Intro"); } State StateIntro(UpdateIntro,DrawIntro,InitIntro,ShutIntro); /******************************************************************************/ // MENU /******************************************************************************/ Bool InitMenu(){return true;} void ShutMenu(){} Bool UpdateMenu() { if(Kb.bp(KB_ESC))return false; // when escape pressed exit application if(Kb.bp(KB_ENTER))StateGame.set(0.5); // when enter pressed set 'StateGame' with 0.5 second smooth fading return true; } void DrawMenu() { D.clear(GREY); D.text (0, 0 ,"Menu"); D.text (0,-0.3,"Press Enter to start the game"); D.text (0,-0.5,"Press Escape to exit"); } State StateMenu(UpdateMenu,DrawMenu,InitMenu,ShutMenu); /******************************************************************************/ // GAME /******************************************************************************/ Bool InitGame(){return true;} void ShutGame(){} Bool UpdateGame() { if(Kb.bp(KB_ESC))StateMenu.set(1.0); // when escape pressed set 'StateMenu' with 1.0 second smooth fading return true; } void DrawGame() { D.clear(TURQ); D.text (0,0,"Game"); } State StateGame(UpdateGame,DrawGame,InitGame,ShutGame); /****************************************************************************** Typically methods will be called in this order: Init() InitIntro() UpdateIntro() DrawIntro() .. UpdateIntro() DrawIntro() ShutIntro() InitMenu () UpdateMenu() DrawMenu() .. UpdateMenu() DrawMenu() ShutMenu() InitGame() UpdateGame() DrawGame() .. UpdateGame() DrawGame() ShutGame() InitMenu() UpdateMenu() DrawMenu() .. UpdateMenu() DrawMenu() ShutMenu() Shut() /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Threads 2.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Flt time; /******************************************************************************/ void Calculate(Real x) { // perform lot's of numerical calculations REP(1000) REP(1000) { x =Cos(Sin(x*x+Sqrt(x))); x+=Pow(10+x,10+x*5); x =Cbrt(Tan(x)); } } /******************************************************************************/ void SingleThreadCalculate() { Calculate(1); Calculate(2); } /******************************************************************************/ Bool ThreadProcA(Thread &thread) { Calculate(1); // perform calculations return false; // stop the thread after calculations } Bool ThreadProcB(Thread &thread) { Calculate(2); // perform calculations return false; // stop the thread after calculations } void MultiThreadCalculate() { // create the threads Thread thread_a(ThreadProcA), thread_b(ThreadProcB); // wait for the threads to finish processing thread_a.wait(); thread_b.wait(); // delete threads thread_a.del(); thread_b.del(); } /******************************************************************************/ void InitPre() { App.name("Threads"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Kb.bp(KB_1)) { time=Tm.curTime(); // get current time SingleThreadCalculate(); // perform calculations on one thread time=Tm.curTime()-time; // get difference between remembered and current time } if(Kb.bp(KB_2)) { time=Tm.curTime(); // get current time MultiThreadCalculate(); // perform calculations on multiple threads time=Tm.curTime()-time; // get difference between remembered and current time } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text(0,0.9,S+"Press 1 for single threaded calculations"); D.text(0,0.8,S+"Press 2 for multi threaded calculations"); D.text(0,0,S+"Time spent for calculations : "+time); REP(3) { Flt a=Tm.time()*2+i*PI2/3; Tri2 t; t.p[0].set(0,0); t.p[1].set(Cos(a ),Sin(a )); t.p[2].set(Cos(a+PI2/9),Sin(a+PI2/9)); (t*0.2-Vec2(0,0.5)).draw(GREY); } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Threads.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Threads are programs (functions) which run simultaneously /******************************************************************************/ // global integers Int x, y[2]; // threads Thread thread_x, thread_y0, thread_y1; /****************************************************************************** Thread functions must be of "Bool name(Thread &thread)" format they return true when wan't to continue thread processing, and false when wan't to stop them as input parameter thread functions receive reference to the Thread which calls them /******************************************************************************/ Bool ThreadProc(Thread &thread_caller) { x++; // simple increase x value return true; // continue processing } Bool ThreadProcWithUserData(Thread &thread_caller) { y[thread_caller.userd]++; // make use of thread_caller 'userd' user data, and increase wanted 'y' (it will be y[0] or y[1]) return true; // continue processing } /******************************************************************************/ void InitPre() { App.name("Threads"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // create threads thread_x .create(ThreadProc , 0,0,100 ); // thread_x will use 'ThreadProc' as it's procedure, and it will be called once in 100 miliseconds thread_y0.create(ThreadProcWithUserData, 0,0,100, Ptr(0)); // thread_y0 will use 'ThreadProcWithUserData' as it's procedure, it will be called once in 100 miliseconds, and it will use '0' as it's user data thread_y1.create(ThreadProcWithUserData, 0,0,100, Ptr(1)); // thread_y1 will use 'ThreadProcWithUserData' as it's procedure, it will be called once in 100 miliseconds, and it will use '1' as it's user data return true; } /******************************************************************************/ void Shut() { // delete threads thread_x .del(); thread_y0.del(); thread_y1.del(); } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); // draw values D.text(0,0.2,S+"x: " +x ); D.text(0,0.1,S+"y[0]: "+y[0]); D.text(0,0.0,S+"y[1]: "+y[1]); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Video Playback.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Theora video; /******************************************************************************/ void InitPre() { App.name("Video Playback"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { if(!video.create("../data/video/test.ogv"))return Exit("Can't create video"); // create video from Theora File return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; video.update(Tm.curTime()); // update video to current application time return true; } /******************************************************************************/ void Draw() { D .clear(); video.draw (); // draw video D .text (0,0.9,S+video.time()); // draw time position of video } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Misc\Zip.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Char text[]={L"This is a simple text which will be compressed using ZLIB compression. 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"}; Byte * compressed, // buffer where compressed data will be stored *decompressed; // buffer where decompressed data will be stored I32 src_size=SIZE(text), compressed_buf_size, compressed_size, decompressed_size; /******************************************************************************/ void InitPre() { App.name("Zip compression"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; // compression { // for compression we'll need buffer which will hould enough data // how much is enough is calculated through 'ZipSize' function and giving source size compressed_buf_size=ZipSize(src_size); // create raw memory buffer able to store 'compressed_buf_size' bytes Alloc(compressed,compressed_buf_size); // compress data // before compressing we must set destination buffer size('compressed_size') to maximum memory available compressed_size=compressed_buf_size; ZipCompress(compressed,compressed_size,text,src_size); // now 'compressed' contains compressed data, and 'compressed_size' is the actual size of compressed data } // decompression { // for decompression we'll need buffer which will hold decompressed data (we know that decompressed size is the size of the source) Alloc(decompressed,src_size); // decompress data // before decompression we must set destination buffer size('decompressed_size') to maximum memory available decompressed_size=src_size; ZipDecompress(decompressed,decompressed_size,compressed,compressed_size); // now 'decompressed' contains decompressed data, and 'decompressed_size' is the actual size of decompressed data } return true; } /******************************************************************************/ void Shut() { // free buffers Free( compressed); Free(decompressed); } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text(0,0.2,S+"Source size: "+src_size); D.text(0,0.1,S+"Compressed size: "+compressed_size); D.text(0,0.0,S+"Buffer size used for compression: "+compressed_buf_size); D.text(0,-0.2,"Source text:" ); D.text(Sin(Tm.time())*2.5,-0.3, text); D.text(0,-0.5,"Decompressed text:"); D.text(Sin(Tm.time())*2.5,-0.6,(Char*)decompressed); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Net\Download.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Gfx gfx; Download download; /******************************************************************************/ void InitPre() { App.name("Downloading file"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; download.create("http://www.esenthel.com/download/logo.gfx"); // create downloader return true; } /******************************************************************************/ void Shut() { download.del(); // delete downloader } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(download.state()==DWNL_DONE) // if all data downloaded successfully { // data can be accessed freely through Download::buf,size methods // for example download.buf()[0] is the first Byte of data // we'll use the downloaded data to load an image from it if(!gfx.is()) // check if we haven't already created it { File f(download.data(),download.size()); // create a file from memory data gfx.load(f); // load a gfx from the file } } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); if(gfx.is()) // when image is downloaded and created gfx.drawFs(); // draw it switch(download.state()) { case DWNL_NONE : D.text(0, 0, "Nothing");break; case DWNL_WAIT : D.text(0, 0, "Awaiting for connection..");break; case DWNL_DOWNLOAD: D.text(0, 0,S+"Downloading.. "+download.done()+'/'+download.size());break; case DWNL_DONE : D.text(0,-0.9, "Done");break; case DWNL_ERROR : D.text(0, 0, "Error encountered");break; } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Net\Ftp.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ void InitPre() { App.name("FTP"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Ftp ftp; // create and Ftp object // login to the FTP if(ftp.login("ftp.host.com","user","password")) // in order to connect to an FTP server you will need to change these parameters to your custom { // sample upload ftp.upload(File("c:/test.file"),"/test.file"); // upload "c:/test.file" to the FTP "/test.file" // sample download File file; file.writeMem(); // open the file for writing to memory ftp.download("/test.file",file); // download "/test.file" from the FTP to 'file' // sample list files Memb<FtpFile> files; // container for the files ftp.listFiles("/",files); // list all files in the root "/" ftp to the 'files' container // logout ftp.logout(); } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; return true; } void Draw() { D.clear(WHITE); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Net\Socket.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** This tutorial presents the most basic socket usage. It needs to be launched few times, so multiple windows of it will appear on the desktop. Each of the program instances (windows) will create it's own 'player' and a socket (internet connection). At the start of the program, it tries to contact other instances (windows) by sending empty data to specific ports. When each of the program instances (windows) receive data from other instances, they store their address in a memory container, as a list of "external players" In the update each instance sends its own player position to all other instances, so they'll know the most recent player position. This way each instance receives data from other instances about their player positions. /******************************************************************************/ #define BASE_PORT 10000 /******************************************************************************/ struct Player // player, contains only a position { Vec2 pos; // position void draw(UInt color) // draw { Circle(0.1,pos).draw(color,true); } Player() // constructor { pos.zero(); } }; struct Peer // peers (external players from other program instances) { SockAddr addr ; // their socket address Player player; // their player data }; /******************************************************************************/ Player player; // this program instance player Socket sock ; // this program instance socket Memb<Peer> peer ; // container of external peers /******************************************************************************/ void InitPre() { App.name("Socket"); App.flag=APP_NO_FX|APP_WORK_IN_BACKGROUND; // specify work in background flag to work also when not focused PakAdd("../data/engine.pak"); D.mode(400,300).sync(true); } Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Text_ds.scale*=2; // create this instance socket (internet connection) { // try to initialize socket on one of the ports starting from BASE_PORT // some ports will not be accessible because other program instances may have already reserved them FREP(50)if(sock.createPeer(BASE_PORT+i))break; // 50 attempts, stops on first usable port sock.block(false); // set non-blocking mode, this will disable waiting when receiving data through socket } // make contact with other sockets created by other program instances { SockAddr addr; // socket address addr.ip("127.0.0.1"); // set address ip to 'localhost', which is your computer FREP(50) // now check 50 ports where possibly other instances of the tutorial have created a socket { addr.port(BASE_PORT+i); // set port of the address if(addr.port()!=sock.port()) // if it's on a different port than our socket (which means that it's not us) sock.send(addr,NULL,0); // send empty data just to contact the other socket to let it know that we exist } } return true; } /******************************************************************************/ void Shut() { sock.del(); peer.del(); } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; // update this instance player position if(App.active() && Ms.b(0)) // when application is active (focused) and left mouse button pushed { player.pos+=Ms.d; // move player position } // send this instance player position to all external players REPA(peer) { sock.send(peer[i].addr,&player.pos,SIZE(player.pos)); } // receive positions from other players for(SockAddr addr;;) { Vec2 pos; Int rcv=sock.receive(addr,&pos,SIZE(pos)); // check if the socket receives any data if( rcv<0)break; // if no data then break // here we've received some data from an external program instance { // first we'll check for its address, and store it on the "external player" list Peer *p=NULL; REPA(peer)if(peer[i].addr==addr){p=&peer[i]; break;} // check if it's already stored on the list if(!p) // if not found in add it { p=&peer.New(); p->addr=addr; } // now we've got the sender stored on the list, so we can check for any data that the external player is sending to us if(rcv==SIZE(pos))p->player.pos=pos; // if number of received data bytes is equal to Vec2 size then it's a new position of the external player } } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); // draw players player.draw(ColorI( sock.port())); // draw this instance player with color depending on its socket port number REPA(peer)peer[i].player.draw(ColorI(peer[i].addr.port())); // draw external players with color depending on their socket port number // draw instructions D.text(0,0.88,"Launch this tutorial multiple times"); D.text(0,0.74,"Press LMB and move the Mouse"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Sound\Music.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ // music themes, each for storing tracks MusicTheme *mt_battle , // this is battle theme used for playing when battles *mt_explore, // exploring theme *mt_calm ; // calm theme /******************************************************************************/ void InitPre() { App.name("Music"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; if(mt_battle=MusicThemeNew()) // create 'mt_battle' theme { *mt_battle+="../data/music/battle0.ogg"; // add "battle0.ogg" track to 'mt_battle' theme *mt_battle+="../data/music/battle1.ogg"; // add "battle1.ogg" track to 'mt_battle' theme } if(mt_explore=MusicThemeNew()) // create 'mt_explore' theme { *mt_explore+="../data/music/explore.ogg"; // add "explore.ogg" track to 'mt_explore' theme } if(mt_calm=MusicThemeNew()) // create 'mt_calm' theme { *mt_calm+="../data/music/calm.ogg"; // add "calm.ogg" track to 'mt_calm' theme } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Kb.c('1'))Music.play(mt_battle ); if(Kb.c('2'))Music.play(mt_explore); if(Kb.c('3'))Music.play(mt_calm ); if(Kb.c('4'))Music.play(NULL ); return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); if(Music.theme) // if any theme playing { D.text(0,0.2,S+"song: "+Music.name()); D.text(0,0.0,S+"time " +Music.time()+" / "+Music.length()+" length"); }else { D.text(0,0,"No theme playing"); } D.text(0,-0.2,"Press 1-battle, 2-explore, 3-calm, 4-none"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Sound\Sound 3D.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Sound sound; // sound Vec pos(0,0,3); // sound position /******************************************************************************/ void InitPre() { App.name("Sound 3D"); App.flag=APP_NO_FX|APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { sound.play("../data/sound/water.ogg",pos,1,true); // play looped 3D sound, volume=1, position='pos' return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|CAMH_ROT); // update all 3D sound positions { sound.pos(pos); // since 'pos' is the same in each frame, the sound position doesn't need to be updated, but let's do it anyway } // update listener parameters { Listener.pos (Cam.matrix.pos ) // set listener position (from camera) .orn (Cam.matrix.z,Cam.matrix.y) // set listener orientation (from camera) .update( ); // updates all 3D parameters, only after this call all changes take effect } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); Ball(1,pos).draw(BLACK); // draw ball at sound position } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Sound\Sound.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Sound sound; // water sound /******************************************************************************/ void InitPre() { App.name("Sound"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC ))return false; if(Kb.bp(KB_SPACE))SoundPlay("../data/sound/metal.ogg"); // play sound on space if(Kb.bp(KB_ENTER)) // toggle water on enter { if(sound.playing()) // if already playing { sound.del(); // delete sound }else { sound.play("../data/sound/water.ogg",true); // play with loop option enabled } } // change volumes on mouse wheel { if(Ms.wheel>0)sound.volume(sound.volume()+0.1);else if(Ms.wheel<0)sound.volume(sound.volume()-0.1); } // change speed on LMB/RMB { if(Ms.b(0))sound.speed(sound.speed()-Tm.d()*0.4); if(Ms.b(1))sound.speed(sound.speed()+Tm.d()*0.4); } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); D.text (0, 0.2, "Press space to play 'metal'"); D.text (0, 0.0,S+"Press enter to stop/play looped 'water' (playing: " +sound.playing()+')'); D.text (0,-0.2,S+"Use mouse wheel to change water sound volume (current: "+sound.volume ()+')'); D.text (0,-0.4,S+ "Press LMB/RMB to change water sound speed (current: " +sound.speed ()+')'); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\1 - Geometry, Graphics, Gui, Misc, Net, Sound\Sound\Volume Groups.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MusicTheme *mt_battle , // music themes *mt_explore ; Sound sound ; // sound Slider vol_fx , // volume bars vol_music , vol_ambient; Text tvol_fx , // volume text tvol_music , tvol_ambient; /******************************************************************************/ void InitPre() { App.name("Volume groups"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Gui.tds_text.scale*=1.5f; // make all Text objects bigger if(mt_battle=MusicThemeNew()) // create mt_battle theme { *mt_battle+="../data/music/battle0.ogg"; // add "battle0.ogg" track to 'mt_battle' theme *mt_battle+="../data/music/battle1.ogg"; // add "battle0.ogg" track to 'mt_battle' theme } if(mt_explore=MusicThemeNew()) // create mt_explore theme { *mt_explore+="../data/music/explore.ogg"; // add "explore.ogg" track to 'mt_explore' theme } Music .play(mt_battle ); // play theme as music Ambient.play(mt_explore); // play theme as ambient sound .play("../data/sound/water.ogg",true); // play looped sound Gui+=vol_fx .create(Rect(-0.1,0.30,0.3,0.40),SoundVolume.fx ()); Gui+=tvol_fx .create(Vec2(-0.3,0.35),"Fx" ); Gui+=vol_music .create(Rect(-0.1,0.15,0.3,0.25),SoundVolume.music ()); Gui+=tvol_music .create(Vec2(-0.3,0.20),"Music" ); Gui+=vol_ambient.create(Rect(-0.1,0.00,0.3,0.10),SoundVolume.ambient()); Gui+=tvol_ambient.create(Vec2(-0.3,0.05),"Ambient"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); // set new volumes SoundVolume.fx (vol_fx ()); SoundVolume.music (vol_music ()); SoundVolume.ambient(vol_ambient()); return true; } /******************************************************************************/ void Draw() { D .clear(WHITE); Gui.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Animation\01 - Animation.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ CSkeleton cskel; /******************************************************************************/ void InitPre() { App.name("Animation"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Cam.dist=2; Cam.yaw =PI; cskel.create("../data/obj/chr/skeleton/0.skel",1.7); // create controlled skeleton from skel file, with 1.7 meter height return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); // set animations { cskel.clear(); // clear controlled skeleton animation if(Kb.b(KB_SPACE)) // when space pressed { cskel.animate(L"../data/anim/walk.anim",Tm.time()); // animate with "walk" animation and current time position } cskel.updateMatrix(MatrixIdentity); // update controlled skeleton animation matrixes cskel.updateVelocities( ); // update controlled skeleton bone velocities (this is needed for Motion Blur effect) } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); // render { LightDir(Vec(0,0,-1)).set(); // set light Meshs("../data/obj/chr/skeleton/0.mesh")->draw(cskel); // get mesh from cache and render it with controlled skeleton matrixes if(Kb.ctrl) // when control pressed { SetMatrix(); // restore default matrix cskel.draw(RED); // draw controlled skeleton } } D.text(0,0.8,"Hold space to animate"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Animation\02 - Skeleton Points.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Skeleton points are special points attached to skeletons They can be used to render items in correct places Skeleton points can be accessed after animating skeleton through CSkeleton::getPoint method, which returns reference to OrientP structure which is an orientation and position /******************************************************************************/ CSkeleton cskel; /******************************************************************************/ void InitPre() { App.name("Skeleton Points"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=2; Cam.yaw =PI; cskel.create("../data/obj/chr/skeleton/0.skel",1.7); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); // set animations cskel.clear().animate(L"../data/anim/walk.anim",Tm.time()).updateMatrix(MatrixIdentity).updateVelocities(); return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); LightDir(Vec(0,0,-1)).set(); // draw mesh Meshs("../data/obj/chr/skeleton/0.mesh")->draw(cskel); // draw skeleton point SetMatrix(); cskel.getPoint("HandR").draw(RED); cskel.getPoint("HandL").draw(RED); cskel.getPoint("Head" ).draw(RED); // draw item in right hand { OrientP &hand_r=cskel.getPoint("HandR"); Matrix m; m.setPosDir(hand_r.pos,hand_r.perp,hand_r.dir) // set position and directions according to skeleton point .scaleOrn(0.7); // scale down the matrix orientation a little, making the item smaller Meshs("../data/obj/item/weapon/blunt/club/0.mesh")->draw(m); // render item with matrix } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Animation\03 - Blending.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ CSkeleton cskel; Flt blend; // blending value (0..1) Bool walk ; // if want to walk /******************************************************************************/ void InitPre() { App.name("Animation Blending"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Text_ds.color =BLACK; Text_ds.shadow=0; Cam.dist=2; Cam.yaw =PI; cskel.create("../data/obj/chr/skeleton/0.skel",1.7); // create controlled skeleton from skel file, with 1.7 meter height return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); if(Kb.bp(KB_SPACE))walk^=1; // change 'walk' when space pressed // adjust blend value if(walk) { blend+=Tm.d()*2; if(blend>1)blend=1; }else { blend-=Tm.d()*2; if(blend<0)blend=0; } // set animations { cskel.clear (); // clear controlled skeleton animation cskel.animate(L"../data/anim/walk.anim",Tm.time(), blend); // animate with "walk" animation, current time position and ' blend' blending weight cskel.animate(L"../data/anim/run.anim" ,Tm.time(), 1-blend); // animate with "walk" animation, current time position and '1-blend' blending weight cskel.updateMatrix(MatrixIdentity).updateVelocities(); // update controlled skeleton animation and velocities } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); LightDir(Vec(0,0,-1)).set(); // render { Meshs("../data/obj/chr/skeleton/0.mesh")->draw(cskel); // get mesh from cache and render it with controlled skeleton if(Kb.ctrl) // when control pressed { SetMatrix(); // restore default matrix cskel.draw(RED); // draw controlled skeleton } } D.text(0,0.8,S+"Press space to toggle blending (Walk: "+walk+", Blend: "+blend+')'); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Animation\04 - Manual Editing.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ CSkeleton cskel; /******************************************************************************/ void InitPre() { App.name("Animation Manual Editing"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=2; Cam.yaw =PI; cskel.create("../data/obj/chr/skeleton/0.skel",1.7); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ROT|CAMH_ZOOM); // set animations { cskel.clear().animate(L"../data/anim/walk.anim",Tm.time()); // set default walking animation Orient &head=cskel.getBone("head").orn; // get head bone orientation head*=Matrix3().setRotateZ(Sin(Tm.time()*1.5)); // rotate head orientation according to time cskel.updateMatrix(MatrixIdentity) // update all matrixes .updateVelocities(); // update all bone velocities } return true; } /******************************************************************************/ void Draw() { D.clear(WHITE); LightDir(Vec(0,0,-1)).set(); // draw Meshs("../data/obj/chr/skeleton/0.mesh")->draw(cskel); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\01 - Physics.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** This tutorial is using PhysX, to run it, you must: -have PhysX SystemSoftware installed from http://developer.nvidia.com/object/physx_downloads.html -have "NxCooking.dll" in your application folder /******************************************************************************/ Actor ground, box , ball ; /******************************************************************************/ void InitPre() { App.name("Physics"); App.flag=APP_MS_EXCLUSIVE|APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.dist=4; // create physics Physics.create(); // create actors ground.create(Box (15,1,15,Vec(0 ,-2, 0)), 0); // create ground actor from Box and density=0 (which means it's a static actor - will not move) box .create(Box (0.3 ,Vec(0.1, 1, 0))); ball .create(Ball(0.3 ,Vec( 0, 0, 0))); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|CAMH_ROT); // physics update { Physics.sim(); // start frame simulation // physics simulation takes some time, so you can do some calculations here // important : you may not modify actors between Physics.sim() and Physics.get() Physics.get(); // get results of frame simulation } Flt s=3; // add forces to ball if(Kb.b(KB_UP ))ball.addForce(Vec(0,0, 1)*s); if(Kb.b(KB_DOWN ))ball.addForce(Vec(0,0,-1)*s); if(Kb.b(KB_LEFT ))ball.addForce(Vec(-1,0,0)*s); if(Kb.b(KB_RIGHT))ball.addForce(Vec( 1,0,0)*s); // add forces to ball according to camera if(Kb.b(KB_W))ball.addForce( !PointOnPlane(Cam.matrix.z,Vec(0,1,0))*s); if(Kb.b(KB_S))ball.addForce(-!PointOnPlane(Cam.matrix.z,Vec(0,1,0))*s); if(Kb.b(KB_A))ball.addForce(-!PointOnPlane(Cam.matrix.x,Vec(0,1,0))*s); if(Kb.b(KB_D))ball.addForce( !PointOnPlane(Cam.matrix.x,Vec(0,1,0))*s); // add velocity to ball if(Kb.bp(KB_SPACE))ball.addVel(Vec(0,3,0)); return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); // draw physical actors } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\02 - Multi shaped actor.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground, ball , actor ; /******************************************************************************/ void InitPre() { App.name("Multi shaped actors"); App.flag=APP_MS_EXCLUSIVE|APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.dist=4; Physics.create(); ground .create(Box (15,1,15,Vec(0,-2,0)), 0); ball .create(Ball(0.3,Vec(0,1.3,0))); ActorCD acd; // multi-shaped actor creation description acd.add(Box (0.2 )); // add box to 'acd' acd.add(Ball(0.2,Vec(-0.3,0.2,0))); // add ball to 'acd' acd.add(Ball(0.2,Vec( 0.3,0.2,0))); // add ball to 'acd' actor.create(acd,Vec(0,0.3,0)); // create actor from 'acd' return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|CAMH_ROT); Physics.sim().get(); return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\03 - Joints.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground, ball , box ; Joint joint ; // joint, used to connect two actors together, or attach one to a fixed point in the world Vec joint_pos , // joint position (used only for drawing) joint_axis; // joint axis (used only for drawing) /******************************************************************************/ void InitPre() { App.name("Joints"); App.flag=APP_MS_EXCLUSIVE|APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.dist =4; Cam.pitch=-0.2; Physics.create(); ground .create(Box_U(15,1,15,Vec(0,0,0)), 0); ball .create(Ball (0.3,Vec(-1,0.3,0))).vel(Vec(5,0,0)); // create a ball on ground and set its initial velocity to right Box_D b(0.1,2,2,Vec(2,0,0)); box.create(b).ignore(ground); // create a box from 'b' and ignore collisions with 'ground' actor joint_pos=b.cornerLDF(); // set joint position to box left-down-front corner joint_axis.set(0,1,0); // set joint axis to up joint.createHinge(box,NULL, joint_pos, joint_axis); // create a hinge joint in order to attach 'box' actor at 'joint_pos' world position and 'joint_axis' axis return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Physics.sim().get(); return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); joint_pos.draw(RED); // draw joint position D.line(GREEN, joint_pos, joint_pos+joint_axis*3); // draw a line from joint position and it's axis } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\04 - Joints 2.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground, box ; Joint joint ; Vec joint_pos, joint_dir; /******************************************************************************/ void InitPre() { App.name("Joints"); App.flag=APP_MS_EXCLUSIVE|APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.dist=4; Physics.create(); ground .create(Box(15,1,15,Vec(0,-2,0)), 0); Box_D b(2,2,0.2); box.create(b); // create a box from 'b' joint_pos=b.cornerLDF(); // set joint position to box left-down-front corner joint_dir.set(1,0,0); // set joint direction to right joint.createSliding(box, NULL, joint_pos, joint_dir, 0, 1.5); // create a sliding joint in order to attach 'box' actor at 'joint_pos' world position, 'joint_dir' direction and 0 .. 1.5 moving limits return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Physics.sim().get(); if(Kb.b(KB_LEFT ))box.addVel(Vec(-Tm.d(),0,0)); // add left velocity if(Kb.b(KB_RIGHT))box.addVel(Vec( Tm.d(),0,0)); // add right velocity if(Kb.b(KB_UP ))box.addVel(Vec(0,0, Tm.d())); // add forward velocity which will not affect the actor if(Kb.b(KB_DOWN ))box.addVel(Vec(0,0,-Tm.d())); // add bacward velocity which will not affect the actor return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); joint_pos.draw(RED); // draw joint position D.line(GREEN, joint_pos, joint_pos+joint_dir*3); // draw a line from joint position and it's direction D.text(0,0.9,S+"Press Left / Right to change velocity"); D.text(0,0.8,S+"Press Up / Down to change velocity, the object won't move because of the joint"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\05 - Controllers.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground , actor[10]; Controller ctrl ; // controller - it's meant to be used as a 'character actor' /******************************************************************************/ void InitPre() { App.name("Character Controllers"); App.flag=APP_MS_EXCLUSIVE|APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam .dist=4; Physics.create(); ground .create(Box(15,1,15,Vec(0,-2,0)), 0); // create random actors REPA(actor)switch(Random(3)) { case 0: actor[i].create(Box (RandomF(0.1,0.5), Random(Box(10,1,10)))); break; case 1: actor[i].create(Ball (RandomF(0.1,0.5), Random(Box(10,1,10)))); break; case 2: actor[i].create(Capsule(RandomF(0.1,0.2),RandomF(0.5,1.0),Random(Box(10,1,10)))); break; } // create controller ctrl.create(Capsule(0.4,1.7)); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button Physics.sim().get(); // update controller (move on WSAD keys, crouch on Shift key, jump on Space key) Flt s=3; Vec vel(0,0,0); if(Kb.b(KB_W))vel+=!PointOnPlane(Cam.matrix.z,Vec(0,1,0))*s; if(Kb.b(KB_S))vel-=!PointOnPlane(Cam.matrix.z,Vec(0,1,0))*s; if(Kb.b(KB_A))vel-=!PointOnPlane(Cam.matrix.x,Vec(0,1,0))*s; if(Kb.b(KB_D))vel+=!PointOnPlane(Cam.matrix.x,Vec(0,1,0))*s; ctrl.update(vel, Kb.shift, Kb.bp(KB_SPACE) ? 3.5 : 0); return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\06 - Testing.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground,ball; /******************************************************************************/ void InitPre() { App.name("Testing"); App.flag=APP_MS_EXCLUSIVE|APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.dist=4; Physics.create(); ground.create(Box (15,1,15,Vec(0,-2,0)), 0); ball .create(Ball(1,Vec(0,3,0))); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button Physics.sim().get(); if(Kb.bp(KB_SPACE))ball.addVel(Vec(0,5,0)); // add velocity to the ball when space pressed return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); // test if custom ray hits some actor { Vec start( 4,0,0), // starting position of ray end (-4,0,0); // ending position of ray PhysHit phys_hit ; // phys-hit object for receiving hit parameters if any if(Physics.ray(start,end-start,&phys_hit)) // if ray hit something { D.line(RED , start, phys_hit.plane.p); // draw a red line from staring position to hit position D.line(GREEN, phys_hit.plane.p, phys_hit.plane.p+phys_hit.plane.n*0.3); // draw a green line presenting the hit normal vector D.dot (RED , phys_hit.plane.p); // draw the contact point }else { D.line(BLUE, start, end); // draw a blue line from starting position to end position } } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\07 - Detecting objects under cursor.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ enum ACTOR_GROUPS // actor groups (for example in the game you can specify following groups: door, item, character, ..) { GROUP_BACKGROUND, // background GROUP_OBJ , // objects }; /******************************************************************************/ Actor ground, obj[10]; /******************************************************************************/ void InitPre() { App.name("Detecting objects under cursor"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.setSpherical(Vec(0,0,-2), 0,-0.7,0, 6).set(); // set camera position and activate it Physics.create(); ground.create(Box(15,1,15,Vec(0,-2,0)), 0).group(GROUP_BACKGROUND); // create ground and set its group to background // create random actors REPA(obj) { switch(Random(3)) { case 0: obj[i].create(Box (RandomF(0.1,0.5), Random(Box(10,1,10)))); break; case 1: obj[i].create(Ball (RandomF(0.1,0.5), Random(Box(10,1,10)))); break; case 2: obj[i].create(Capsule(RandomF(0.1,0.2),RandomF(0.5,1.0),Random(Box(10,1,10)))); break; } obj[i].group(GROUP_OBJ).userd(i); // set actor's group to 'object' group and set its user data, in this tutorial it'll be index of the object in the array } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Physics.sim().get(); return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); // we'll now test if mouse points on some actor // to do that we'll perform a standard ray testing // with initial ray 'start' point located near the camera, and 'end' point located as far as viewport range reaches { // to obtain 'start' and 'end' point we'll use a special function called 'ScreenToPosDir' which transforms a screen position (Vec2) to world space position and direction Vec screen_pos, screen_dir; ScreenToPosDir(Ms.pos, screen_pos, screen_dir); // obtain 'screen_pos' and 'screen_dir' from Mouse cursor position // now having world space position and direction we can calculate ray 'start' and 'end' positions Vec start=screen_pos, end =screen_pos + screen_dir*Viewport.range; // having ray positions we can perform a ray test PhysHit phys_hit; if(Physics.ray(start,end-start,&phys_hit)) // if ray hit something { D.text(0,0.9, "Ray has hit an actor!"); D.text(0,0.8,S+"Actor's group: " +phys_hit.group); D.text(0,0.7,S+"Actor's user data (index): "+phys_hit.userd); }else { D.text(0,0.9,"Ray hasn't hit anything"); } } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\08 - Grabbing.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground, // ground obj ; // object Grab grab ; // grabber /******************************************************************************/ void InitPre() { App.name("Grabbing objects"); App.flag=APP_NO_FX; PakAdd("../data/engine.pak"); D.sync(true); } Bool Init() { Cam.setSpherical(Vec(0,0,-2), 0,-0.7,0, 6).set(); // set camera position and activate it Physics.create(); ground.create(Box(15,1,15,Vec(0,-2,0)), 0); // create ground obj .create(Box(0.3 ) ); // create object return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Physics.sim().get(); if(Kb.ctrl) // if want to grab { if(!grab.is()) // if not yet grabbing { grab.create(obj,Vec(0,0.3,0),10); // start grabbing 'obj' actor at (0,0.3,0) local position with a power of 10 } if(grab.is()) // if grabbing something { // drag the object to left/right/forward/backwards Vec dir(0); if(Kb.b(KB_LEFT ))dir.x--; if(Kb.b(KB_RIGHT))dir.x++; if(Kb.b(KB_DOWN ))dir.y--; if(Kb.b(KB_UP ))dir.y++; grab.pos(grab.pos()+dir*Tm.d()*2); } }else { if(grab.is())grab.del(); } return true; } /******************************************************************************/ void Draw() { D .clear(); Physics.draw (); if(!grab.is())D.text(0,0.9,"Hold Control to grab the object"); else D.text(0,0.9,"Use the arrow keys to drag around the object"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\09 - Physical meshes.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Controller ctrl ; // character controller MeshGroup mshg ; // mesh group (used for rendering) PhysGroup phsg ; // physical mesh group (used for collisions) Memb<Actor> actor; // container of actors that will be created out of 'phsg' /******************************************************************************/ void InitPre() { App.name("Physical meshes"); App.flag=APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true); } Bool Init() { Cam.dist=6; Physics.create(); ctrl.create(Capsule(0.4,1.7,Vec(0,1,0))); // create character controller mshg.load ("obj/terrain/0.mshg"); // load terrain MeshGroup phsg.create(mshg); // create physical body group (PhysGroup) from 'mshg' FREPA(phsg) // for all physical bodies (Phys) inside 'phsg' { Actor &a=actor.New(); // create new Actor in container a.create(phsg.phys(i)); // create that Actor from i-th Phys in 'phsg' } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button Physics.sim().get(); // update controller (move on WSAD keys, crouch on Shift key, jump on Space key) Flt s=3; Vec vel(0,0,0); if(Kb.b(KB_W))vel+=!PointOnPlane(Cam.matrix.z,Vec(0,1,0))*s; if(Kb.b(KB_S))vel-=!PointOnPlane(Cam.matrix.z,Vec(0,1,0))*s; if(Kb.b(KB_A))vel-=!PointOnPlane(Cam.matrix.x,Vec(0,1,0))*s; if(Kb.b(KB_D))vel+=!PointOnPlane(Cam.matrix.x,Vec(0,1,0))*s; ctrl.update(vel, Kb.shift, Kb.bp(KB_SPACE) ? 3.5 : 0); return true; } /******************************************************************************/ void Draw() { D.clear(); LightDir(Cam.matrix.z).set(); mshg .draw(MatrixIdentity); // draw mesh Physics.draw( ); // draw physics } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\10 - Ragdoll.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground , // ground actor box[3] ; // stairs CSkeleton cskel ; // controlled skeleton Ragdoll ragdoll; // ragdoll /******************************************************************************/ void SetPose() { cskel.clear().updateMatrix(Matrix().setRotateX(0.45).move(Vec(0,3,0))).updateVelocities(); // set skeleton animation to default pose and custom matrix ragdoll.fromSkel(cskel); // setup ragdoll from skeleton animation } /******************************************************************************/ void InitPre() { App.name("Ragdoll"); App.flag=APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true); Cam.dist =5; Cam.pitch=-0.3; Cam.yaw =PI; } Bool Init() { Physics.create(); ground.create(Box_U(15,1,15,Vec(0,-1,0)),0); REPA(box)box[i].create(Box(1,Vec(0,i*0.5-0.5,i*-0.5-0.3)),0); cskel .create("obj/chr/skeleton/0.skel",1.8); // create skeleton ragdoll.create(cskel); // create ragdoll from skeleton SetPose(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button Physics.sim().get(); ragdoll.toSkel(cskel); // set skeleton from ragdoll if(Kb.bp(KB_SPACE))SetPose(); return true; } /******************************************************************************/ void Draw() { D.clear(); LightDir(Cam.matrix.z).set(); Meshs("obj/chr/skeleton/0.mesh")->draw(cskel); Physics.draw(); D.text(0,0.9,"Press Space to reset simulation"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\11 - Vehicle.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Flt angle ; // car wheel angle Actor car , // car actor ground ; // ground actor Wheel wheel[4]; // wheels /******************************************************************************/ void InitPre() { App.name("Vehicle"); App.flag=APP_FULL_TOGGLE|APP_NO_FX; PakAdd("../data/engine.pak"); D.mode(800,600).sync(true); ViewportFull.range=200; } Bool Init() { Cam.dist=10; Physics.create(); ground .create(Box_U(100,1,100),0); ground .pos (ground.pos()-Vec(0,3,0)); // create car car.create (Box(2,1,4)); // create actor car.massCenter(car.massCenter()-Vec(0,1.0,0)); // lower mass center // create car wheels Wheel::Param wp; // wheel parameters wheel[0].create(car,Vec( 1,-0.5, 1.5),wp); wheel[1].create(car,Vec(-1,-0.5, 1.5),wp); wheel[2].create(car,Vec( 1,-0.5,-1.5),wp); wheel[3].create(car,Vec(-1,-0.5,-1.5),wp); return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1f,200,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Physics.sim().get(); if(Kb.bp(KB_ENTER))car.pos(Vec(0,3,0)); // reset car position on ENTER key // adjust car controls { angle=LerpTime(angle,(Kb.b(KB_D)-Kb.b(KB_A))*PI_4,0.01); // adjust wheel angle Flt accel=(Kb.b(KB_W)-Kb.b(KB_S))*1600, // acceleration brake= Kb.b(KB_SPACE) *3200; // brakes wheel[0].angle(angle); // set angle wheel[1].angle(angle); // set angle wheel[2].accel(accel).brake(brake); // set acceleration and brakes wheel[3].accel(accel).brake(brake); // set acceleration and brakes } // update wheels REPAO(wheel).update(); return true; } void Draw() { D .clear(); Physics.draw (); (car.massCenter()*car.matrix()).draw(RED); // draw mass center } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Physics\12 - Cloth.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Actor ground, box , ball ; Cloth cloth ; // Physical Cloth /******************************************************************************/ void InitPre() { App.name("Physical Clothes"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); D.mode(1024,768).sync(true); } Bool Init() { Cam.dist =4; Cam.pitch=-PI_4; Physics.create(); ground.create(Box (15,1,15,Vec( 0,-2,0)), 0); box .create(Box (0.3 ,Vec(-1, 0,0))); ball .create(Ball(0.3 ,Vec( 1, 0,0))); // create cloth Cloth::Param param; // parameters for cloth creation Mshb mshb ; // clothes are created from meshes, so create a mesh for it mshb .createPlane(32,32,VTX_TX0) // create mesh as 32x32 vertex plane with texture coordinates set .transform(Matrix().setRotateX(PI_2).move(Vec(-0.5,1,-0.5)).scale(3)); // transform mesh by matrix cloth.create(mshb,Materials("../data/mtrl/ground/0.mtrl"),param); // create cloth from mesh return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Physics.sim().get(); return true; } /******************************************************************************/ void Draw() { LightDir(Cam.matrix.z).set(); D .clear(); Physics.draw (); cloth .draw (); // draw cloth } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\01 - Rendering.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mesh; /******************************************************************************/ void InitPre() { App.name("Rendering"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=2; mesh.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG); // create Mesh with 1 Mshb, and create this Mshb from Ball with automatic texture coordinates, normals and tangents mesh.setMaterial(Materials("../data/mtrl/brick/0.mtrl")).setRender().setBox(); // set mesh material, rendering version and bounding box return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(1.5,10,CAMH_ZOOM|CAMH_ROT); return true; } /******************************************************************************/ void Render() // Rendering Method { switch(Renderer()) // Rendering Method will be called multiple times with different Rendering Modes { // first there is "solid rendering" mode where you need to render all solid meshes case RM_SOLID: mesh.draw(MatrixIdentity); break; // then there is "light rendering" mode where you need to render all the lights case RM_LIGHT: LightDir(Vec(0,0,1)).add(); break; } } void Draw() { // instead of typical "D.clear(WHITE);" we'll now use advanced rendering : Renderer(Render); // render with 'Render' method D.text(0,0.9,S+"Fps: "+Tm.fps()); // show number of fps } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\02 - Sky.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mesh; // sample mesh Gfx gfx ; // sky box texture /******************************************************************************/ void InitPre() { App.name("Rendering Sky"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.mode(800,600); ViewportFull.range=20; // set initial viewport range to 20 meters to see sky fog when zoomed out } /******************************************************************************/ Bool Init() { Cam.dist=6; // create mesh mesh.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG); mesh.setMaterial(Materials("../data/mtrl/brick/0.mtrl")).setRender().setBox(); // import skybox gfx.Import("../data/gfx/sky/skybox.jpg",GFX_A8R8G8B8,GFX_CUBE); // set default sky Sky.set(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(2.5,18,CAMH_ZOOM|CAMH_ROT); if(Kb.bp(KB_1))Sky.clear( ); // disable sky if(Kb.bp(KB_2))Sky.set (Vec(0.35,0.45,0.64),Vec(0.30,0.38,0.54)); // set sky from colors if(Kb.bp(KB_3))Sky.set (gfx ); // set sky from skybox return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: REPD(x,3) REPD(z,3)mesh.draw(Matrix(1,Vec(x-1,0,z-1)*3)); break; case RM_LIGHT: LightDir(!Vec(1,-1,1)).add(); break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press 1,2,3 for different skies"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\03 - Fog.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Material *brick, *glass; Mesh mbox , mball; Vec pos[64]; Window window; Slider fog_frac, fog_exp ; Text tfog_frac, tfog_exp ; /******************************************************************************/ void InitPre() { App.name("Fog"); App.flag=APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true).bloom(0.8,0.6,0.3,true); ViewportFull.range=25; // hide mouse Ms.hide(); } /******************************************************************************/ Bool Init() { brick=Materials("../data/mtrl/brick/0.mtrl"); glass=Materials("../data/mtrl/glass/0.mtrl"); mbox .create(1).base(0).create( Box( 10),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(0.5),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(brick).setRender().setBox(); mball.setMaterial(glass).setRender().setBox(); // set random positions inside box REPA(pos)pos[i]=Random(mbox.box); // set camera Cam.at = mbox.box.cornerLDF()/2; Cam.dist = 10; Cam.pitch=-PI_4; Cam.yaw = PI_4; // set Sky and initial fog parameters Sky.set (Vec(0.3),Vec(0.3)) .fogFrac(0); // add gui fog controls Gui +=window .create(Rect_C(0,-0.75,0.9,0.34),"Fog Parameters").hide(); window+=tfog_frac.create(Vec2(0.2,-0.08),"Fraction"); window+=fog_frac.create(Rect_C(0.2+window.crect.w()/2,-0.08,0.25,0.05),Sky.fogFrac()).desc("Fraction of the Viewport Range where the Fog starts"); window+=tfog_exp .create(Vec2(0.2,-0.16),"Exponent"); window+=fog_exp .create(Rect_C(0.2+window.crect.w()/2,-0.16,0.25,0.05),Sky.fogExp ()).desc("Fog Density"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); CamHandle(0.01,100,Ms.hidden() ? CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT) : 0); // when mouse hidden operate the camera if(Kb.bp(KB_TAB)) { Ms .toggle (); // toggle mouse visibility when tab pressed window.visibleToggleActivate(); // toggle window visibility when tab pressed } // set fog parameters Sky.fogFrac( fog_frac() ) .fogExp (Pow(fog_exp (),16)); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity); REPA(pos) { glass->color.v3=ColorVec(ColorHue(Flt(i)/ELMS(pos))); glass->validate(); mball.draw(Matrix(pos[i])); } break; case RM_LIGHT: LightPoint(40,Vec(0,0,0)).add(); break; } } void Draw() { Renderer(Render); Gui.draw(); if(Ms.hidden())D.text(0,0.9,S+"Press Tab to toggle parameters"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\04 - Suns.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain; /******************************************************************************/ void InitPre() { App.name("Suns"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3).hpRt(true).hwDepthBuffer(true); Cam.pitch=0.5f; } Bool Init() { terrain.load("obj/terrain/0.mshg"); // terrain Sky.set(); // sky // sun { Sun &sun=Suns.New(); // create a new sun in 'Suns' container sun.set(*Gfxs("gfx/sky/sun.gfx")); // set image sun.pos=!Vec(1,1,1); // set custom position } // moon { Sun &moon=Suns.New(); // create a new sun in 'Suns' container moon.set(*Gfxs("gfx/sky/moon.gfx")); // set image moon.pos =!Vec(-1,1,1); // set custom position moon.size*=0.6; // decrease default size moon.blend=false; // disable blending, and thus set adding mode moon.gfx_color=0x00404040; // set gfx color moon.light_color=0; // disable light casting moon.rays.mode=SUN_RAYS_OFF; // disable sun rays for the moon } return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,500,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: terrain.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\05 - Bumpmapping.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox , mball; /****************************************************************************** In this tutorial we'll dynamically show different Bump Mapping modes Changing Bump Mapping modes in runtime requires reseting shader effects of manually created Meshes To achieve this we need to create a function which will reset effects of those meshes: /******************************************************************************/ void SetEffect() { mbox .setEffect(); mball.setEffect(); } /******************************************************************************/ void InitPre() { App.name("Rendering Bumpmapping"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.set_effect=SetEffect ; // set 'SetEffect' function to be used when needed D.full(true).bumpMode(BUMP_FLAT); // start with flat bump mapping } /******************************************************************************/ Bool Init() { Cam.dist=3; Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox .create(1).base(0).create( Box(4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(material).setRender().setBox(); mball.setMaterial(material).setRender().setBox(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button // change bump mapping when keys pressed if(Kb.bp(KB_1))D.bumpMode(BUMP_FLAT ); if(Kb.bp(KB_2))D.bumpMode(BUMP_NORMAL ); if(Kb.bp(KB_3))D.bumpMode(BUMP_PARALLAX); if(Kb.bp(KB_4))D.bumpMode(BUMP_RELIEF ); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox .draw(MatrixIdentity); mball.draw(MatrixIdentity); break; case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); D.text(0,0.8,"Press 1,2,3,4 keys for different Bumpmapping modes"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\06 - Viewport.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox , mball; /******************************************************************************/ void InitPre() { App.name("Viewport"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true); } /******************************************************************************/ Bool Init() { Cam.dist=3; Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox .create(1).base(0).create( Box(4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(material).setRender().setBox(); mball.setMaterial(material).setRender().setBox(); return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox .draw(MatrixIdentity); mball.draw(MatrixIdentity); break; case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; } } void Draw() { // render to active viewport Renderer(Render); // render to another viewport { // set new viewport Rect rect(-D.w(),-D.h(),0,0); // setup viewport rectangle to left bottom quarter rect.extend(-0.05); // extend with negative value, to make it smaller Viewport.set(rect); // set viewport with given rectangle // render everything once again Renderer(Render); // restore default viewport by activating ViewportFull ViewportFull.set(); } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\07 - Motion Blur.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ struct Object { Matrix matrix; // matrix Vec vel, // linear velocity ang_vel; // angular velocity }object[12]; /******************************************************************************/ Mesh mbox , mball; /******************************************************************************/ void InitPre() { App.name("Rendering Motion Blur"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true).mtnMode(MTN_HIGH); // enable motion blur D.mtnVelScale(0.20); // increase motion blurring } /******************************************************************************/ Bool Init() { Cam.dist=3; Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox .create(1).base(0).create( Box( 4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(0.2),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(material).setRender().setBox(); mball.setMaterial(material).setRender().setBox(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT)); // move camera on right mouse button // change motion blur mode when keys pressed if(Kb.bp(KB_1))D.mtnMode(MTN_NONE); if(Kb.bp(KB_2))D.mtnMode(MTN_LOW ); if(Kb.bp(KB_3))D.mtnMode(MTN_HIGH); // update ball object matrixes and calculate velocity changes automatically Flt speed=4; REPA(object) { // calculate new matrix Vec2 v; SinCos(v.y,v.x, i*PI2/ELMS(object) + Tm.time()*speed); // calculate sine and cosine of angle Matrix new_matrix(Vec(v.x,0,v.y)); // create 'new_matrix' with initial position // calculate velocity changes according to old and new matrix GetVel(object[i].vel,object[i].ang_vel, object[i].matrix,new_matrix); // store new matrix object[i].matrix=new_matrix; } return true; } /******************************************************************************/ void Render() // rendering method { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity,Vec(0,0,0)); // box is rendered with identity matrix and (0,0,0) velocity REPA(object)mball.draw(object[i].matrix,object[i].vel,object[i].ang_vel); // draw ball objects with their matrix and velocities break; case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); // show number of fps D.text(0,0.8,"Press 1,2,3 keys for different Motion Blur modes"); switch(D.mtnMode()) { case MTN_NONE: D.text(0,0.7,"No Motion Blur" ); break; case MTN_LOW : D.text(0,0.7,"Camera only" ); break; case MTN_HIGH: D.text(0,0.7,"Camera + Objects"); break; } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\08 - Materials.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Material material_brick, material_fur, material_glow, material_rfl; Mesh mesh; /******************************************************************************/ void InitPre() { App.name("Rendering Materials"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); D.full(true); } /******************************************************************************/ Bool Init() { Cam.dist=4; material_brick.reset(); // setup defaults material_brick.diffuse=Gfxs("../data/mtrl/brick/0.gfx" ); // set diffuse texture material_brick.normal =Gfxs("../data/mtrl/brick/0.n.gfx"); // set normal texture material_brick.detail =Gfxs("../data/mtrl/brick/det.gfx"); // set detail texture material_fur.reset(); // setup defaults material_fur.technique=MTECH_FUR; // set fur technique material_fur.det_power =1; // in fur technique 'det_power' is used for fur length material_fur.det_scale/=2; // in fur technique 'det_scale' is used for fur scale material_glow.reset(); // setup defaults material_glow.glow=0.5; // set glow amount material_rfl.reset(); // setup defaults material_rfl.diffuse =Gfxs("../data/mtrl/glass/0.gfx" ); // set diffuse texture to white material_rfl.normal =Gfxs("../data/mtrl/glass/0.n.gfx"); // set normal texture material_rfl.reflection=Gfxs("../data/mtrl/glass/rfl.gfx"); // set reflection texture material_rfl.color.set(1,0.66,0.33,0); // set color material_rfl.specular=0.5 ; // set specular material_rfl.bump =0.09; // set bump value material_rfl.rough =0.05; // set roughness material_rfl.reflect =0.8 ; // set reflection mesh.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG); // create Mesh with 1 Mshb, and create this Mshb from Ball and automatic texture coordinates, normals and tangents mesh.setRender().setBox(); // set mesh rendering version and bounding box return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(1.5,10,CAMH_ZOOM|CAMH_ROT); if(Ms.b(0)) // on left mouse button change colors of materials { material_glow .color.x=0.5; material_brick.color.y=0.5; material_fur .color.z=0.5; }else { // restore default rgb color values material_glow .color.v3=1; material_brick.color.v3=1; material_fur .color.v3=1; } // validate changes material_glow .validate(); material_brick.validate(); material_fur .validate(); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_FUR : // here since fur technique is being used we must process also 'RM_FUR' mode, in it we can simply render everything which is in 'RM_SOLID' mode case RM_SOLID: mesh.setMaterial(&material_glow ).draw(Matrix(Vec(-1, 1,0))); mesh.setMaterial(&material_brick).draw(Matrix(Vec( 1, 1,0))); mesh.setMaterial(&material_fur ).draw(Matrix(Vec( 1,-1,0))); mesh.setMaterial(&material_rfl ).draw(Matrix(Vec(-1,-1,0))); break; case RM_LIGHT: LightDir(Vec(0,0,1)).add(); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\09 - Shadows.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox , // mesh box mball; // mesh ball /******************************************************************************/ void InitPre() { App.name("Rendering Shadows"); App.flag=APP_MS_EXCLUSIVE; PakAdd("../data/engine.pak"); } /******************************************************************************/ Bool Init() { Cam.dist=3; Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox .create(1).base(0).create( Box(3),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(material).setRender().setBox(); mball.setMaterial(material).setRender().setBox(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(1.5,10,CAMH_ZOOM|CAMH_ROT); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox .draw(MatrixIdentity); mball.draw(MatrixIdentity); break; case RM_LIGHT: LightPoint(10,Vec(Cos(Tm.time()),Sin(Tm.time()),-1.5)).add(); break; // since we want to render shadows we have to process additional rendering mode 'RM_SHD_MAP' (render shadows through shadow maps) // here we will render all meshes which cast shadows case RM_SHD_MAP: mball.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); // show number of fps } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\10 - Volumetric Lights.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox, // mesh box mmb ; // mesh middle barrier /******************************************************************************/ void InitPre() { App.name("Volumetric Lights"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; // mouse exclusive, display can be toggled with Alt+Enter PakAdd("../data/engine.pak"); D.mode(1024,700).volLight(true); // enable volumetric lighting } /******************************************************************************/ Bool Init() { Cam.dist=8; Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox.create(1).base(0).create(Box(3) ,VTX_TX0|VTX_NRM|VTX_TNG).reverse(); mmb .create(1).base(0).create(Box(6,1,6),VTX_TX0|VTX_NRM|VTX_TNG); // make hole inside 'mmb' by subtracting from it a temporary box (3D geometry subtraction will be used) { Mshb temp; temp.create(Box(1),VTX_TX0|VTX_NRM|VTX_TNG); // create temporary box mmb .base(0).csg(temp,SEL_SUB); // subtract 'temp' from 'mmb' mmb.setNormals().setTangents().setBinormals(); // re-create normals tangents and binormals } mbox.setMaterial(material).setRender().setBox(); mmb .setMaterial(material).setRender().setBox(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(2,10,CAMH_ZOOM|CAMH_ROT); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity); mmb .draw(MatrixIdentity); break; case RM_LIGHT: LightPoint(5,Vec(Cos(Tm.time()),1,Sin(Tm.time())),Vec(1), 0.1).add(); // render light with volumetric amount set to 0.1 break; case RM_SHD_MAP: mbox.draw(MatrixIdentity); // volumetric lighting depends on shadow map, so we need to render 'mbox' too mmb .draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\11 - Ambient Occlusion.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** In this tutorial is presented how to achieve high ambient lighting value with satisfactionary looks /******************************************************************************/ struct AmbientControls { Window win; Text tmode,tsoft,tjitter,thalf_res,tpower,tcontrast,trange,tscale,tbias; ComboBox mode, soft; CheckBox jitter,half_res; Slider power,contrast,range,scale,bias; void create() { static CChar8 *modes[]= { "off", "low", "high #1", "high #2", "high #3", "high #4", }; static CChar8 *softing[]= { "0", "1", "2", }; Flt y=0,h=0.062; Gui+= win .create(Rect_RD(D.w(),-D.h(),0.9,0.67),"Ambient Parameters").hide(); y-=h; win+=tmode .create(Vec2 (0.2,y),"Mode" ); win+=mode .create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),modes ,ELMS(modes )).set(D.ambMode()); y-=h; win+=tsoft .create(Vec2 (0.2,y),"Soft" ); win+=soft .create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),softing,ELMS(softing)).set(D.ambSoft()); y-=h; win+=tjitter .create(Vec2 (0.2,y),"Jitter" ); win+=jitter .create(Rect_C(0.2+win.crect.w()/2,y,0.05,0.05),D.ambJitter () ); y-=h; win+=thalf_res.create(Vec2 (0.2,y),"Half Resolution"); win+=half_res.create(Rect_C(0.2+win.crect.w()/2,y,0.05,0.05),D.ambHalfRes () ); y-=h; win+=tpower .create(Vec2 (0.2,y),"Power" ); win+=power .create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),D.ambPower () ); y-=h; win+=tcontrast.create(Vec2 (0.2,y),"Contrast" ); win+=contrast.create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),D.ambContrast()/4 ); y-=h; win+=trange .create(Vec2 (0.2,y),"Range" ); win+=range .create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),D.ambRange ()/0.4); y-=h; win+=tscale .create(Vec2 (0.2,y),"3D Scale" ); win+=scale .create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),D.ambScale ()/4 ); y-=h; win+=tbias .create(Vec2 (0.2,y),"Bias" ); win+=bias .create(Rect_C(0.2+win.crect.w()/2,y,0.25,0.05),D.ambBias () ); y-=h; } }AC; /******************************************************************************/ Mesh mbackground, mball, mbox ; Matrix matrix_ball[25], matrix_box [25]; /******************************************************************************/ void InitPre() { App.name("Ambient Occlusion"); App.flag=APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true).ambMode(AMB_HIGH3).ambSoft(1).ambJitter(1).ambHalfRes(1).ambPower(0.8); // set initial ambient occlusion parameters Ms.hide(); // hide mouse } /******************************************************************************/ Bool Init() { Cam.dist=5; Material *brick=Materials("../data/mtrl/brick/0.mtrl"), *glass=Materials("../data/mtrl/glass/0.mtrl"); mbackground.create(1).base(0).create( Box(3 ),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create background box mbox .create(1).base(0).create( Box(0.5),VTX_TX0|VTX_NRM|VTX_TNG); // create box mball .create(1).base(0).create(Ball(0.5),VTX_TX0|VTX_NRM|VTX_TNG); // create ball mbackground.setMaterial(brick).setRender().setBox(); mbox .setMaterial(glass).setRender().setBox(); mball .setMaterial(glass).setRender().setBox(); // setup random matrixes REPA(matrix_ball)matrix_ball[i].setRotateXY(RandomF(PI2),RandomF(PI2)).move(Random(mbackground.box)); REPA(matrix_box )matrix_box [i].setRotateXY(RandomF(PI2),RandomF(PI2)).move(Random(mbackground.box)); AC.create(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); CamHandle(0.01,100,Ms.hidden() ? CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT) : 0); // when mouse hidden operate the camera if(Kb.bp(KB_TAB)) { Ms .toggle (); // toggle mouse visibility when tab pressed AC.win.visibleToggleActivate(); // toggle window visibility when tab pressed } // set Ambient Occlusion parameters D.ambMode (AC.mode ()) .ambSoft (AC.soft ()) .ambJitter (AC.jitter ()) .ambHalfRes (AC.half_res()) .ambPower (AC.power ()) .ambContrast(AC.contrast()*4) .ambRange (AC.range ()*0.4) .ambScale (AC.scale ()*4) .ambBias (AC.bias ()); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbackground.draw(MatrixIdentity); REPA(matrix_ball)mball.draw(matrix_ball[i]); REPA(matrix_box )mbox .draw(matrix_box [i]); break; } } void Draw() { Renderer(Render); Gui.draw(); if(Ms.hidden())D.text(0,0.9,S+"Press Tab to toggle parameters"); else D.text(0,0.9,S+"Fps: "+Tm.fps()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\12 - Early Z.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** EarlyZ is a technique of rejecting pixels which aren't visible Another way of doing this optimization is to sort objects manually before rendering, so they will be rendered in front-to-back order. - Advantage of EarlyZ is that it's simpler to use and it's pixel-precise, instead of object-precise as in manual object sorting -Disadvantage is that it requires additional pass of rendering, but fortunately it consists only of vertex transformations and z-buffer setting /******************************************************************************/ Mesh mbox , mball; /******************************************************************************/ void InitPre() { App.name("Early Z"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true).bumpMode(BUMP_RELIEF); // setup relief bump mapping to enable pixel-heavy processing } /******************************************************************************/ Bool Init() { Cam.dist=3; Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox .create(1).base(0).create( Box(5),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); mball.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG); mbox .setMaterial(material).setRender().setBox(); mball.setMaterial(material).setRender().setBox(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); return true; } /******************************************************************************/ void Render() { // to use EarlyZ just render in 'RM_EARLY_Z' mode all big objects which occlude others switch(Renderer()) { case RM_EARLY_Z: // in this tutorial we'll simply render the same things as in 'RM_SOLID' mode if(!Kb.b(KB_SPACE)) // disable EarlyZ when space pressed { mbox .draw(MatrixIdentity); FREP(5)mball.draw(Matrix(2,Vec(0,0,5-i))); // draw in back-to-front order to present EarlyZ speedup } break; case RM_SOLID: mbox .draw(MatrixIdentity); FREP(5)mball.draw(Matrix(2,Vec(0,0,5-i))); // draw in back-to-front order to present EarlyZ speedup break; case RM_LIGHT: LightPoint(25,Vec(0,3,-1)).add(); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps: "+Tm.fps()); D.text(0,0.8, "Hold Space to disable EarlyZ"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\13 - Bloom.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Material *brick, *glass; Mesh mbox , mball; Vec pos[32]; Window window; Text tbloom_org, tbloom_scale, tbloom_cut, tbloom_overbright; Slider bloom_org, bloom_scale, bloom_cut; CheckBox bloom_overbright; /******************************************************************************/ void InitPre() { App.name("Bloom configuration"); App.flag=APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true); } /******************************************************************************/ Bool Init() { Cam.dist=3; brick=Materials("../data/mtrl/brick/0.mtrl"); glass=Materials("../data/mtrl/glass/0.mtrl"); mbox .create(1).base(0).create( Box( 4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(0.5),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(brick).setRender().setBox(); mball.setMaterial(glass).setRender().setBox(); // set random positions inside box REPA(pos)pos[i]=Random(mbox.box); // add gui bloom controls Gui +=window.create(Rect_C(0,-0.7,0.6,0.5),"Bloom Parameters"); window+=tbloom_org .create(Vec2(0.13,-0.08),"Origin" ); window+=bloom_org .create(Rect_C(0.1+window.crect.w()/2,-0.08,0.25,0.05),D.bloomOriginal ()); window+=tbloom_scale .create(Vec2(0.13,-0.16),"Scale" ); window+=bloom_scale .create(Rect_C(0.1+window.crect.w()/2,-0.16,0.25,0.05),D.bloomScale ()); window+=tbloom_cut .create(Vec2(0.13,-0.24),"Cutoff" ); window+=bloom_cut .create(Rect_C(0.1+window.crect.w()/2,-0.24,0.25,0.05),D.bloomCut ()); window+=tbloom_overbright.create(Vec2(0.13,-0.32),"OverBright" ); window+=bloom_overbright.create(Rect_C(0.1+window.crect.w()/2,-0.32,0.05,0.05),D.bloomOverbright()); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); Cam.setSpherical(Vec(0,0,0),Tm.time()/16,-0.3,0,3).updateVelocities().set(); // set autorotating camera D.bloom(bloom_org(),bloom_scale(),bloom_cut(),bloom_overbright()); // set bloom parameters return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity); REPA(pos) { glass->color.v3=ColorVec(ColorHue(Flt(i)/ELMS(pos))); mball.draw(Matrix(pos[i])); } break; case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; } } void Draw() { Renderer(Render); Gui.draw(); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\14 - Depth of Field.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Material *brick, *glass; Mesh mbox , mball; Vec pos[32]; Window window; CheckBox dof_hi; ComboBox dof_blurs; Slider dof_power, dof_range; Text tdof_hi, tdof_blurs, tdof_power, tdof_range; /******************************************************************************/ void InitPre() { App.name("Depth of Field"); App.flag=APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true).dof(DOF_HIGH,1, 1,0,5); // set initial depth of field parameters // hide mouse Ms.hide(); } /******************************************************************************/ Bool Init() { brick=Materials("../data/mtrl/brick/0.mtrl"); glass=Materials("../data/mtrl/glass/0.mtrl"); mbox .create(1).base(0).create( Box( 4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(0.5),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(brick).setRender().setBox(); mball.setMaterial(glass).setRender().setBox(); // set random positions inside box REPA(pos)pos[i]=Random(mbox.box); // set camera Cam.at = mbox.box.cornerLDF()/2; Cam.dist = 10; Cam.pitch=-PI_4; Cam.yaw = PI_4; // add gui Dof controls static CChar8 *blurs[]= { "1", "2", "3", }; Gui +=window .create(Rect_C(0,-0.7,0.9,0.50),"Depth of Field Parameters").hide(); window+=tdof_hi .create(Vec2(0.2,-0.08),"High Quality"); window+=dof_hi .create(Rect_C(0.2+window.crect.w()/2,-0.08,0.05,0.05),D.dofMode ()==DOF_HIGH).desc("Prevents foreground objects leaking into background"); window+=tdof_blurs.create(Vec2(0.2,-0.16),"Blurs" ); window+=dof_blurs.create(Rect_C(0.2+window.crect.w()/2,-0.16,0.25,0.05),blurs,ELMS(blurs)).set(D.dofBlurs()-1); window+=tdof_power.create(Vec2(0.2,-0.24),"Power" ); window+=dof_power.create(Rect_C(0.2+window.crect.w()/2,-0.24,0.25,0.05),D.dofPower()); window+=tdof_range.create(Vec2(0.2,-0.32),"Range" ); window+=dof_range.create(Rect_C(0.2+window.crect.w()/2,-0.32,0.25,0.05),D.dofRange()/10); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); CamHandle(0.01,100,Ms.hidden() ? CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT) : 0); // when mouse hidden operate the camera if(Kb.bp(KB_TAB)) { Ms .toggle (); // toggle mouse visibility when tab pressed window.visibleToggleActivate(); // toggle window visibility when tab pressed } // set depth of field parameters D.dof(dof_hi () ? DOF_HIGH : DOF_ON, dof_blurs()+1, dof_power(), Cam.dist, dof_range()*10); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity); REPA(pos) { glass->color.v3=ColorVec(ColorHue(Flt(i)/ELMS(pos))); glass->validate(); // changing parameters realtime requires calling 'validate' mball.draw(Matrix(pos[i])); } break; case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; } } void Draw() { Renderer(Render); Gui.draw(); if(Ms.hidden())D.text(0,0.9,S+"Press Tab to toggle parameters"); else D.text(0,0.9,S+"Fps "+Tm.fps()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\15 - Particles.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox; Particles part[4]; // particles /******************************************************************************/ void InitPre() { App.name("Particles"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true); Cam.dist=2; } /******************************************************************************/ Bool Init() { // create mesh box mbox.create(1).base(0).create(Box(4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); mbox.setMaterial(Materials("mtrl/brick/0.mtrl")).setRender().setBox(); // create particles { // we'll start with a fire-like particle Gfx *gfx =Gfxs("gfx/particle/fire.gfx"); // image UInt col =ARGB(0,40,0,0); // color Int num =30; // number Flt r =0.1, // radius life =1.0, // average life vel =0.2; // random velocity Vec accel(0,1,0); // acceleration Shape shape(Ball(0.05)); // particles initial shape part[0].create(*gfx,col,num,r,life,vel,accel,shape); // create particles part[0].set (Vec(-0.5,0,0) ); // move to the left part[0].reset ( ); // reset every single particle for random position and other parameters // let's set part[1] with different settings, to make it magic-like { gfx =Gfxs("gfx/particle/fire.gfx"); col =ARGB(0,0,0,40); num =100; r =0.05; life=1.0; vel =0; accel.zero(); shape=Capsule(0.1,0.4); part[1].create(*gfx,col,num,r,life,vel,accel,shape); // create particles part[1].reset ( ); // reset every single particle part[1].func=PARTICLE_SIN; // change particles power function to sinus based } // and now part[2], fountain-like { gfx =Gfxs("gfx/particle/drop.gfx"); col =ARGB(150,20,120,200); // part[2] will be rendered in a different way (alpha blended) so make sure to set up alpha value in the color num =500; r =0.02; life=1.0; vel =1.0; accel.set(0,-2,0); shape=Vec(0,0,0); part[2].create(*gfx,col,num,r,life,vel,accel,shape); // create particles part[2].set (Vec(0.5,0,0) ); // move to the right part[2].vel.set(2,2,0); // set initial vector velocity part[2].damping=0.98; // enable damping part[2].reset( ); // reset every single particle } // part[3], smoke-like { gfx =Gfxs("gfx/particle/fire.gfx"); col =ARGB(100,0,0,0); // part[3] will be rendered in a different way (alpha blended) so make sure to set up alpha value in the color num =40; r =0.15; life=1.5; vel =0.2; accel.zero(); shape=Vec(0,0,0); part[3].create(*gfx,col,num,r,life,vel,accel,shape); // create particles part[3].set (Vec(-1,0,0) ); // move to the left part[3].reset ( ); // reset every single particle } } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // modify part[3] position Vec2 pos; SinCos(pos.y,pos.x,Tm.time()+PI); part[3].set(Vec(pos.x,0,pos.y)); // update particles REPA(part)part[i].update(); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity); break; case RM_LIGHT: LightPoint(30,Vec(0,3,0)).add(); break; // particles are rendered in RM_PALETTE or RM_BLEND modes // the first one (RM_PALETTE) is for objects rendered using color palette, and take their colors from 'Renderer.color_palette' texture (you can assign this texure to your custom version with command "Renderer.color_palette=Gfxs(..)") // the second one (RM_BLEND ) is for objects rendered with standard alpha blending // let's render part[0] and part[1] as pallette based, and part[2] and part[3] with standard alpha blending case RM_PALETTE: // palette based part[0].draw(); part[1].draw(); break; case RM_BLEND: // alpha blending part[2].draw(); part[3].draw(); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\16 - Blood.txt /******************************************************************************/ #include "stdafx.h" #include <EsenthelEngine/EsenthelEngine.h> /******************************************************************************/ Mesh *chr ; // character mesh Gfx *main , // main blood texture *single; // single blood texture BloodFx blood ; // blood particle effect /******************************************************************************/ void InitPre() { App.name("Blood Effect"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak",NULL); Cam.dist=3; D.full(1).hpRt(true); } /******************************************************************************/ Bool Init() { Sky.set(); chr=Meshs("obj/chr/human/0.mesh"); main =Gfxs("gfx/particle/blood/0.gfx"); single=Gfxs("gfx/particle/blood/1.gfx"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1f,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // enable blood effect if(Kb.bp(KB_SPACE)) // on space blood.create(main,single,0xFF800000,60,Vec(0,1,0),Vec(1.6,0,0),1); // create blood effect // update blood effect blood.update(); return true; } /******************************************************************************/ Void Render() { switch(Renderer()) { case RM_SOLID: case RM_SHD_MAP: chr->draw(Matrix(2).rotateY(PI)); // draw character mesh break; case RM_LIGHT: LightPoint(5,Vec(0,1,-1)).add(); break; case RM_BLEND: blood.draw(); // draw Blood Effect in Alpha Blending mode break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to enable Blood Effect"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\17 - Explosion.txt /******************************************************************************/ #include "stdafx.h" #include <EsenthelEngine/EsenthelEngine.h> /******************************************************************************/ Mesh *chr , // character mesh box ; // box mesh Gfx *main , // main explosion texture *single ; // single explosion texture ExplosionFx explosion; // explosion particle effect /******************************************************************************/ void InitPre() { App.name("Blood Effect"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak",NULL); Cam.dist=3; D.full(1).bumpMode(BUMP_PARALLAX).mtnMode(MTN_HIGH); // Explosion Effect makes use of Motion Blur } /******************************************************************************/ Bool Init() { box.create(1).base(0).create(Box(2),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); box.setMaterial(Materials("mtrl/brick/0.mtrl")).setRender().setBox(); chr=Meshs("obj/chr/human/0.mesh"); main =Gfxs("gfx/particle/explosion/0.gfx"); single=Gfxs("gfx/particle/explosion/1.gfx"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; // enable explosion effect if(Kb.bp(KB_SPACE)) // on space { explosion.create(main,single,0x00600000,32,Vec(0,0,0),1); // create explosion effect QuakeFx.addMedium(); // add medium earth quake } // update Explosion Effect explosion.update(); // update Quake Effect QuakeFx.update(); CamHandle(0.1f,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); return true; } /******************************************************************************/ Void Render() { switch(Renderer()) { case RM_SOLID : case RM_SHD_MAP: box .draw(MatrixIdentity); chr->draw(Matrix(2).rotateY(PI)); break; case RM_LIGHT: LightPoint(5,Vec(0,1,-1)).add(); break; case RM_PALETTE: explosion.draw(); // draw Explosion Effect in Color Palette mode break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to enable Explosion Effect"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\18 - Holographic Images.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox,mball; Gfx gfx; Flt density_factor=0.05; /******************************************************************************/ void InitPre() { App.name("Holographic Images"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.1); } /******************************************************************************/ Bool Init() { Cam.dist=3; // create standard meshes and materials Material *material=Materials("mtrl/brick/0.mtrl"); mbox .create(1).base(0).create( Box(5),VTX_TX0|VTX_NRM|VTX_TNG).reverse( ); mbox .setMaterial(material).setRender().setBox(); mball.create(1).base(0).create(Ball(1),VTX_TX0|VTX_NRM|VTX_TNG).weldVal(VTX_POS); mball.setMaterial(material).setRender().setBox(); // create holographic image Int size=64; gfx.create(size,size,size,GFX_A8R8G8B8,GFX_3D,1); // size x size x size dimensions, A8R8G8B8 type, 3D mode, 1 mip map if(gfx.lock()) // start manual pixel editing { REPD(z,gfx.z()) REPD(y,gfx.y()) REPD(x,gfx.x()) { Flt fx=Flt(x)/(gfx.x()-1), // x pixel fraction value 0..1 fy=Flt(y)/(gfx.y()-1), // y pixel fraction value 0..1 fz=Flt(z)/(gfx.z()-1); // z pixel fraction value 0..1 Flt px=fx*2-1, // x pixel position value -1..1 py=fy*2-1, // y pixel position value -1..1 pz=fz*2-1; // z pixel position value -1..1 Vec4 color=0; if(x<=1 || x>=gfx.x()-2 || y<=1 || y>=gfx.y()-2 || z<=1 || z>=gfx.z()-2) // if current pixel is on border { color.set(0,1,0, RandomF(0.5,1)); // green color with random alpha } else // if current pixel is inside { // blue sphere Flt length=Vec(px,py,pz).length(); Flt sphere=(1-Sat(Abs(length-0.5)*8));//*RandomF(); // red fade Flt red_fade=0.5*fx*fx*RandomF(); // color value from blue sphere and red fade if(Flt sum=sphere+red_fade) // total alpha value color.set(1*red_fade/sum, 0.5*sphere/sum, 1*sphere/sum, sum); } gfx.color3DF(x,y,z,color); // store the pixel color } gfx.unlock(); // end pixel editing } REP(3)gfx.sharpen(1,1,true,true); // sharpen the image 3 times return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,1000,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); if(Kb.b(KB_Q))density_factor/=1+Tm.d(); if(Kb.b(KB_W))density_factor*=1+Tm.d(); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID : case RM_SHD_MAP: mbox .draw(MatrixIdentity); mball.draw(Matrix(Vec(0,-3,0))); break; case RM_LIGHT: LightPoint(20,Vec(0,3,3)).add(); break; case RM_BLEND: // holographic images need to be drawn in RM_BLEND mode gfx.draw3D(WHITE,0, Matrix(Vec(1,1,1),Vec(0)), density_factor, 1, 4,64); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps: "+Tm.fps()); D.text(0,0.8,S+"Density Factor: "+density_factor+" (Q/W to change)"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\19 - Layered Clouds.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain; /******************************************************************************/ void InitPre() { App.name("Layered Clouds"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3); } Bool Init() { terrain.load ("obj/terrain/0.mshg"); // terrain Sky .set (); // sky Suns .New().set ( *Gfxs("gfx/sky/sun.gfx")); // sun Clouds .layered.set(3,Gfxs("Clouds/Layers/0.gfx")); // clouds return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,500,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); if(Kb.bp(KB_F10))Renderer.screenShots("screenshot/","bmp"); if(Kb.bp(KB_F11))D.toggle(); if(!Kb.b(KB_SPACE))Clouds.layered.update(); // if space not pressed then update clouds position return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: terrain.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\20 - Volumetric Clouds.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ struct DisplayOptions { Window window; CheckBox vol, hp_rt, hdr; Text tvol,thp_rt,thdr; void create() { Gui +=window.create(Rect_R(D.w(),0.5,0.8,0.35),"Display Options"); window+=vol .create(Rect (0.05,-0.10,0.10,-0.05)); window+=tvol .create(Vec2(0.45,-0.075),"Volumetric Lighting"); window+=hp_rt .create(Rect (0.05,-0.18,0.10,-0.13)); window+=thp_rt.create(Vec2(0.45,-0.155),"High Precision RenderTargets"); window+=hdr .create(Rect (0.05,-0.26,0.10,-0.21)); window+=thdr .create(Vec2(0.45,-0.235),"High Dynamic Range"); } void update() { D.volLight(vol ()); D.hpRt (hp_rt()); D.hdr (hdr ()); } }Opt; /******************************************************************************/ struct CloudImages { Window window; Button generate,save,load; Gfx cloud,detail; static void Generate(Ptr) { if(!Ci.detail.is()) // if detail image hasn't yet been created { CreateVolumetricDetail(Ci.detail,128,16,128); // create volumetric detail image, this image is used in cloud image creation, and it also can be used in the drawing process for additional quality Ci.detail.blur(1,false); // blur it } CreateVolumetricCloud(Ci.cloud,&Ci.detail, 256,32,256, 3, false, 80); Ci.cloud.lumFromAlphaAndLight(DIRF_RIGHT|DIRF_DOWN|DIRF_FORWARD,1.0); Tm .skipUpdate(); // generating clouds is slow, so don't update timer in this frame } static void Save(Ptr){Ci.cloud.save("LocalData/cloud.gfx"); Ci.detail.save("LocalData/detail.gfx");} static void Load(Ptr){Ci.cloud.load("LocalData/cloud.gfx"); Ci.detail.load("LocalData/detail.gfx");} void create() { Gui +=window .create(Rect_LD(-D.w(),-D.h(),0.5,0.3),"Cloud Images"); window+=generate.create(Rect_C (window.rect.w() /2,-0.08,0.35,0.06),"Generate",Generate); window+=save .create(Rect_C (window.rect.w()*1/3,-0.18,0.15,0.06),"Save" ,Save ); window+=load .create(Rect_C (window.rect.w()*2/3,-0.18,0.15,0.06),"Load" ,Load ); Clouds.volumetric.set(&cloud,NULL); } }Ci; /******************************************************************************/ struct CloudParams { Window window; Slider dns, shd, col0, col1, scale, curve, height; Text tdns,tshd,tcol0,tcol1, tscale,tcurve,theight; CheckBox detail, hi_res; Text tdetail,thi_res; Button save , load ; static void Save(Ptr){ Clouds.volumetric.save("LocalData/volumetric_clouds"); } static void Load(Ptr){if(Clouds.volumetric.load("LocalData/volumetric_clouds"))Cp.cloudsToGui();} void create() { Gui+=window.create(Rect_RD(D.w(),-D.h(),0.6,0.77),"Cloud Parameters"); window+=tdns .create(Vec2(0.15,-0.05),"Density"); window+=dns .create(Rect_LU(0.3,-0.03,0.25,0.05), 3.0/6); window+=tshd .create(Vec2(0.15,-0.10),"Shadow" ); window+=shd .create(Rect_LU(0.3,-0.08,0.25,0.05), 0.5 ); window+=tcol0.create(Vec2(0.15,-0.15),"Color0" ); window+=col0.create(Rect_LU(0.3,-0.13,0.25,0.05), 0.38 ); window+=tcol1.create(Vec2(0.15,-0.20),"Color1" ); window+=col1.create(Rect_LU(0.3,-0.18,0.25,0.05), 0.7 ); window+=tscale .create(Vec2(0.15,-0.30),"Scale" ); window+=scale .create(Rect_LU(0.3,-0.28,0.25,0.05), 0.5); window+=tcurve .create(Vec2(0.15,-0.35),"Curve" ); window+=curve .create(Rect_LU(0.3,-0.33,0.25,0.05), 0.5); window+=theight.create(Vec2(0.15,-0.40),"Height"); window+=height.create(Rect_LU(0.3,-0.38,0.25,0.05), 0.5); window+=tdetail.create(Vec2(0.20,-0.50),"Detail" ); window+=detail.create(Rect(0.40,-0.53,0.45,-0.48)); window+=thi_res.create(Vec2(0.20,-0.57),"High Resolution"); window+=hi_res.create(Rect(0.40,-0.60,0.45,-0.55)); window+=save.create(Rect_C(0.17,-0.67,0.18,0.06),"Save",Save); window+=load.create(Rect_C(0.43,-0.67,0.18,0.06),"Load",Load); } void cloudsToGui() { dns .set(Clouds.volumetric.density/6); shd .set(Clouds.volumetric.shadow); col0.set(Clouds.volumetric.dark_color .avg()); col1.set(Clouds.volumetric.bright_color.avg()); scale .set(LerpR(0.125f,0.375f,Clouds.volumetric.scale )); curve .set(LerpR(0.000f,0.060f,Clouds.volumetric.curve )); height.set(LerpR(0.000f,1.540f,Clouds.volumetric.height)); detail.set(Clouds.volumetric.detail!=NULL); hi_res.set(Clouds.volumetric.hi_res ); } void guiToClouds() { Clouds.volumetric.density=Lerp(0,6,dns()); Clouds.volumetric.shadow =Lerp(0,1,shd()); Clouds.volumetric.dark_color .set(col0()); Clouds.volumetric.bright_color.set(col1()); Clouds.volumetric.scale =Lerp(0.125f,0.375f,scale ()); Clouds.volumetric.curve =Lerp(0.000f,0.060f,curve ()); Clouds.volumetric.height=Lerp(0.000f,1.540f,height()); Clouds.volumetric.detail=(detail() ? &Ci.detail : NULL); Clouds.volumetric.hi_res=hi_res(); } }Cp; /******************************************************************************/ MeshGroup terrain; /******************************************************************************/ void InitPre() { App.name("Volumetric Clouds"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3).hdrExposure(0.7); } Bool Init() { terrain.load("obj/terrain/0.mshg"); Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")); // gui Opt.create(); Ci .create(); Cp .create(); return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,500,Ms.hidden() ? CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT) : 0); // when mouse hidden operate the camera if(Kb.bp(KB_TAB)) { Ms . toggle(); // toggle mouse visibility when tab pressed Opt.window.visibleToggle(); Ci .window.visibleToggle(); Cp .window.visibleToggle(); } Gui.update(); Opt.update(); Cp .guiToClouds(); if(Kb.bp(KB_F10))Renderer.screenShots("screenshot/","bmp"); if(Kb.bp(KB_F11))D .toggle(); if(!Kb.b(KB_SPACE))Clouds.volumetric.update(Vec2(4,4)); // if space not pressed then update clouds position by given velocity return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: terrain.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); Gui.draw(); D.text(0,0.9,S+"Fps "+Tm.fps()); D.text(0,0.8,Ms.hidden() ? "Press Tab to toggle parameters" : "Press Tab to operate the camera"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\21 - Object Clouds.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain ; Gfx image[3]; // cloud images struct Cloud { Gfx *gfx; Matrix matrix; Cloud() { gfx=NULL; } void draw(UInt color,UInt color_add) { if(gfx)gfx->draw3D(color,color_add, matrix, 0.5, 0.5); } }; Memb<Cloud> clouds; // container of clouds /******************************************************************************/ void InitPre() { App.name("Object Clouds"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3).hpRt(true); Cam.dist =1; Cam.yaw =2.8; Cam.pitch=0.3; Cam.at.set(0,0,0); ViewportFull.range=200; } Bool Init() { terrain.load("obj/terrain/0.mshg"); Sky.set(); { Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")); sun.rays.mode=SUN_RAYS_HIGH; } // create cloud images Gfx detail; CreateVolumetricDetail(detail, 32,16,32); detail.blur(1,false); REPA(image) { CreateVolumetricCloud(image[i],&detail, 64,32,64, 3, true, 80); image[i].mulAdd(Vec4(1,1,1,4),Vec4(0,0,0,0)); // scale alpha value image[i].lumFromAlphaAndLight(DIRF_RIGHT|DIRF_DOWN|DIRF_FORWARD,0.5); } Flt average_size=4; // holographic images may not intersect with each other, so set positions based on a regular grid modified by slight rotations and offsets for(Int x=-2; x<=2; x++) for(Int z=-2; z<=2; z++) { Cloud &cloud=clouds.New(); // set random image cloud.gfx=&image[Random(ELMS(image))]; // set cloud matrix cloud.matrix.setScale(average_size*RandomF(0.8,1.2)) .scale (Vec(1,0.5,1)) .rotateXY(RandomF(-0.1,0.1),RandomF(-0.4,0.4)) .move ((Vec(x,0,z)+Random.vec(-0.25,0.25))*average_size*2) .move (Vec(0,10,0)); } return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,500,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); return true; } /******************************************************************************/ Int Compare(Cloud &c0,Cloud &c1) { return CompareTransparencyOrder(c0.matrix.pos,c1.matrix.pos); } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: terrain.draw(MatrixIdentity); break; case RM_CLOUD: // clouds in order to affect the sun rays must be drawn in RM_CLOUD mode { Flt color_dark =0.38, color_bright=0.78; UInt color = ColorBrightness(color_bright-color_dark) , color_add =ColorAlpha(ColorBrightness( color_dark),0); // clouds are transparent so they need to be sorted before rendering clouds.sort(Compare); // draw the clouds REPAO(clouds).draw(color,color_add); }break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\22 - Water.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain; /******************************************************************************/ void InitPre() { App.name("Water"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3).hpRt(true).hwDepthBuffer(true); Cam.at.set(0,2,0); Cam.pitch=-0.5; Cam.dist =30; Cam.yaw =2.8; } Bool Init() { terrain.load("obj/terrain/0.mshg"); // terrain terrain.scale(Vec(1,10,1)).move(Vec(0,5,0)); // scale and move terrain vertically Sky .set(); // sky Suns.New().set(*Gfxs("gfx/sky/sun.gfx")); // sun Water.set(*Gfxs("gfx/water/0.gfx"),*Gfxs("gfx/water/0.n.gfx"),Gfxs("gfx/fx/reflection.gfx")); // set water from textures return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,500,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // here you can optionally set different water surface plane if(Kb.b(KB_UP ))Water.plane(Water.plane() + Vec(0,1,0)*Tm.d()); // move water surface plane upwards if(Kb.b(KB_DOWN))Water.plane(Water.plane() - Vec(0,1,0)*Tm.d()); // move water surface plane downwards // update water waves movement Water.update(Vec2(0.2,0.2)); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { // When rendering water, an additional rendering mode has to be used // RM_SOLID_M is "rendering solid in mirrors / water surfaces" mode // for the most simplicity you can render the same things as in RM_SOLID mode case RM_SOLID : case RM_SOLID_M: terrain.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); D.text(0,0.8,"Press up/down keys to change water level"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\23 - Markers.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain; Marker marker[2]; // 2 markers /******************************************************************************/ void InitPre() { App.name("Markers"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3); Cam.pitch=-0.5; Cam.dist =10; } Bool Init() { terrain.load("obj/terrain/0.mshg"); Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")); // setup markers REPA(marker) { Marker &m=marker[i]; m.glow =0; m.color=(i ? YELLOW : RED); m.gfx =Gfxs("gfx/particle/star.gfx"); m.size =2; m.range_opaque=0.2; m.range_fade =0.3; m.local_matrix.setPosDir(Vec(0,0,0), Vec(0,1,0)); // setup matrix to (0,0,0) position, facing up (0,1,0) // set matrix position at terrain surface PosPointMeshY(Vec2(i ? 1 : -1, 0),terrain,&m.local_matrix.pos); } return true; } void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,500,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // rotate markers matrix in their Z axis according to time delta REPA(marker)marker[i].local_matrix.orn.rotateZVec(Tm.d()); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: terrain.draw(MatrixIdentity); break; // markers can be rendered in RM_OVERLAY, RM_BLEND and RM_PALETTE modes, in this tutorial we'll use RM_BLEND case RM_BLEND: REPA(marker)marker[i].draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\24 - Mesh Outline.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Material *brick, *glass; Mesh mbox , mball; Vec pos[32]; /******************************************************************************/ void InitPre() { App.name("Depth of Field"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true); } /******************************************************************************/ Bool Init() { brick=Materials("mtrl/brick/0.mtrl"); glass=Materials("mtrl/glass/0.mtrl"); mbox .create(1).base(0).create( Box( 4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box, reverse it because it's meant to be viewed from inside mball.create(1).base(0).create(Ball(0.5),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh ball // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(brick).setRender().setBox(); mball.setMaterial(glass).setRender().setBox(); // set random positions inside box REPA(pos)pos[i]=Random(mbox.box); // set camera Cam.dist=5; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; case RM_SOLID: mbox.draw(MatrixIdentity); REPA(pos) { glass->color.v3=ColorVec(ColorHue(Flt(i)/ELMS(pos))); glass->validate(); mball.draw(Matrix(pos[i])); } break; // when we wan't to use Mesh Outlining we need to process additional rendering mode 'RM_OUTLINE' case RM_OUTLINE: if(Kb.b(KB_SPACE)) // outline only when space pressed { Renderer.outlineUse(); // outlining mode is optional, and when used the engine needs to be notified about it Flt alpha=Frac(Tm.time()*2,2); if( alpha>1)alpha=2-alpha; REPA(pos) // for all balls { UInt hue=ColorHue (Flt(i)/ELMS(pos)), col=ColorAlpha(hue,alpha); SetHighlight(col); // before drawing the mesh, set highlight color mball.draw(Matrix(pos[i])); // now draw the mesh } } break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to outline the balls"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\25 - Laser and Electricity.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mbox ; Vec point[32]; // laser can be drawn out of an array of points, this is such an array which will be filled with circle coordinates // instead of drawing one laser, we will render few of them, each with it's own vertical position struct Laser { Flt position_y, velocity_y; }laser[]= { {0, 0.4}, {0, 0.6}, {0, 0.8}, {0,-0.4}, {0,-0.6}, {0,-0.8}, }; ElectricityFx electricity; // electricity effect /******************************************************************************/ void InitPre() { App.name("Laser"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true); } /******************************************************************************/ Bool Init() { Cam.dist=3; // create standard meshes and materials Material *material=Materials("../data/mtrl/brick/0.mtrl"); mbox.create(1).base(0).create(Box(4),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); mbox.setMaterial(material).setRender().setBox(); // setup point array for laser REPA(point) { Flt angle=Lerp(PI_4, -PI-PI_4, i/Flt(ELMS(point)-1)); // linearly interpolate angle from 'i' (0..point elements) point[i].set(Cos(angle),0,Sin(angle)); // set point positions on a circle } // setup electricity effect control points electricity.original.New().set(-1,0,-1); electricity.original.New().set( 0,0, 1); electricity.original.New().set( 1,0,-1); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button // update laser positions REPA(laser) { Laser &l=laser[i]; // update lasers position l.position_y+=l.velocity_y*Tm.d(); // if position is too high or to low then change the sign of velocity, so the laser will start moving in a different direction if(l.position_y>1 || l.position_y<-1)CHS(l.velocity_y); } // update electricity electricity.update(); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mbox.draw(MatrixIdentity); break; case RM_LIGHT: LightPoint(25,Vec(0,3,0)).add(); break; } // draw laser and electricity in RM_LIGHT and RM_SOLID modes switch(Renderer()) { case RM_LIGHT: case RM_SOLID: { // draw laser REPA(laser) { SetMatrix(Matrix(Vec(0,laser[i].position_y,0))); // setup matrix for the laser DrawLaser(ARGB(128,128,0,0), ARGB(128,128,0,0), 1, 0.005, false, point,ELMS(point)); // here alpha determines glow amount } // draw electricity SetMatrix(Matrix(Vec(0,-1.5,1))); electricity.draw(); }break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\26 - Cel Shading.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Material glass; Mesh mball; Vec pos[32]; /******************************************************************************/ void InitPre() { App.name("Cel Shading"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true); } /******************************************************************************/ Bool Init() { // set cel shading D.bumpMode (BUMP_FLAT ); // cel-shading works best with flat bump mapping D.hpRt (true ); // cel-shading works best with high precision render targets D.edgeDetect(EDGE_DETECT_FAT); // set edge detection Renderer.cel_shade_palette=Gfxs("gfx/fx/cel light palette.gfx"); // set light palette which modifies global lighting // set sky, material and mesh Sky.set(); glass.reset(); mball.create(1).base(0).create(Ball(0.5),VTX_TX0|VTX_NRM|VTX_TNG); mball.setMaterial(glass).setRender().setBox(); REPA(pos)pos[i]=Random(Box(8,4,8,Vec(0,2,0))); Cam.dist=10; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_LIGHT: { LightDir(!Vec(1,-1,1)).add(); }break; case RM_SOLID: { Mshgs("obj/terrain/0.mshg")->draw(MatrixIdentity); REPA(pos) { glass.color.v3=ColorVec(ColorHue(Flt(i)/ELMS(pos))); glass.validate(); mball.draw(Matrix(pos[i])); } }break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\2 - Animation, Physics, Rendering\Rendering\27 - Multi-Threaded Rendering.txt /******************************************************************************/ #include "stdafx.h" #include <EsenthelEngine/EsenthelEngine.h> /****************************************************************************** In order to take advantage of multiple cores on your CPU, multi-threaded rendering is used. It works by rendering graphics on one thread, and processing data on the other. To avoid multi-threaded issues you need to store your game data in two versions: -backuped data (which contains only data required for rendering, like position and mesh) -normal data (which contains all the data of your object, including position, mesh and other custom parameters) Multi-threaded rendering will look like this: +-------------------------+-----------------------+ | Thread 1 | Thread 2 | +-------------------------+-----------------------+ | Backup your data | | +-------------------------+-----------------------+ | Process the data update | Render 3D graphics | +-------------------------+-----------------------+ | Wait until rendered | | +-------------------------+-----------------------+ | Draw 2D graphics | | +-------------------------+-----------------------+ While Rendering 3D graphics on other thread: - you must not modify 'Viewport' viewport or activate another viewport - you must not modify 'Cam' camera or activate another camera - you must not call methods changing rendering matrixes/velocities (SetMatrix, SetVel, SetAngVel, CSkeleton::setMatrix) Note: Performance gains may vary depending on: -your system (mainly GPU & CPU - number of cores and general performance) -amount of calculations in update -amount of objects rendered /******************************************************************************/ struct ObjectBackup // game object backup - contains only data required for rendering { Vec pos; Mesh *mesh; void draw() // rendering method { mesh->draw(Matrix(pos)); // render 'mesh' at 'pos' position } }; struct Object // game object { Flt parameters[256]; Vec pos; Mesh *mesh; // note that this structure doesn't contain any rendering method, as we'll be rendering only through ObjectBackup::draw void backup(ObjectBackup &dst) // backup data method { // backup all data needed for rendering here dst.pos =pos; dst.mesh=mesh; } Object(){Zero(T);} }; /******************************************************************************/ Bool multi_threaded; // if multi-threaded mode Mesh mbox , // mesh box mball; // mesh sphere Memb<Object > mobj ; // Object's memory block Memb<ObjectBackup> mobj_backup; // ObjectBackup's memory block /******************************************************************************/ void Render() { switch(Renderer()) { case RM_EARLY_Z: case RM_SHD_MAP: case RM_SOLID : mbox.draw(MatrixIdentity); REPA(mobj_backup)mobj_backup[i].draw(); // render backuped data break; case RM_LIGHT: LightPoint(1,Vec(0,0.8,0)).add(); break; } } void Render3D() { Renderer(Render); } void Draw2D() { D.text(0,0.9,multi_threaded ? "Multi-threaded rendering" : "Single-threaded rendering"); D.text(0,0.8,S+"CPU Cores "+Cpu.cores()); D.text(0,0.7,S+"Fps " +Tm .fps ()); D.text(0,0.6, "Press 1,2 to change rendering mode"); } /******************************************************************************/ void InitPre() { App.name("Multi-Threaded Rendering"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak",NULL); D.full(true).bumpMode(BUMP_PARALLAX).shdSoft(2); } /******************************************************************************/ Bool Init() { // create materials Material *brick=Materials("../data/mtrl/brick/0.mtrl"); // create meshes mbox .create(1).base(0).create(Box (1 ),VTX_TX0|VTX_NRM|VTX_TNG).reverse(); // create mesh box mball.create(1).base(0).create(Ball(0.08),VTX_TX0|VTX_NRM|VTX_TNG) ; // create mesh sphere // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(brick).setRender().setBox(); mball.setMaterial(brick).setRender().setBox(); // create some objects REP(256) { Object &obj=mobj.New(); // create new object in container obj.pos =Random(mbox.box); // set it's random position obj.mesh=&mball; // set it's mesh } if(Cpu.cores()>1) // if we have more than one core { StateMain.threadedSet(Render3D); // set StateMain (our current state) to have multi-threaded rendering multi_threaded=true; } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01f,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // toggle multi-threaded rendering when keys pressed if(Kb.bp(KB_1)){StateActive->threadedSet(NULL ); multi_threaded=false;} // disable multi-threaded rendering when '1' pressed if(Kb.bp(KB_2)){StateActive->threadedSet(Render3D); multi_threaded=true ;} // enable multi-threaded rendering when '2' pressed // 4 steps of multi-threaded processing { // 1st - Backup data mobj.backup(mobj_backup); // backup all object's to object_bkp's // 2nd - Start multi-threaded rendering StateActive->threadedStart(); // after this call, Render3D will be working on the second thread // 3rd - Process data update here REPA(mobj) { Object &obj=mobj[i]; // do some heavy floating point operations REPA(obj.parameters)obj.parameters[i]+=Sqrt(Sin(i*PI)*Pow(i,i*2.0)*16); } // 4th - Stop multi-threaded rendering (if it hasn't finished yet, it will wait for it) if(StateActive->threadedStop()) { // if we're here then multi-threaded rendering is enabled, so we need to call 2D drawing manually Draw2D(); } } return true; } /******************************************************************************/ void Draw() // if multi-threaded rendering is enabled, classic 'Draw' will not be called { Render3D(); Draw2D(); D.text(0,-0.9,"Rendering through 'Draw'"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Grass 2.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain ; // terrain mesh Grass grass ; // grass renderer Grass::Elm grass_elm[4096]; // single grass element /******************************************************************************/ void InitPre() { App.name("Grass"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).ambPower(0.3).shdMapSize(1024); ViewportFull.range=50; } /******************************************************************************/ Bool Init() { Cam.dist=6; Cam.at.set(0,2,0); Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")); // load terrain mesh terrain.load("obj/terrain/0.mshg"); // create grass renderer grass.create(); // set random grass matrixes terrain.setFaceNormals(); // make sure terrain has face normals, since we'll need those later REPA(grass_elm) { Grass::Elm &elm =grass_elm[i]; Matrix &matrix=elm.matrix; elm.param.set(0,0,0,255); // set parameters matrix.setScale(Vec(0.18,0.3,0.18)).rotateY(RandomF(PI2)); // set scaled matrix and rotate it Vec start=Random(terrain.box); // set random position at top of the terrain mesh box start.y=terrain.box.max.y; I32 hit_face,hit_mshb,hit_mesh; if(SweepPointMesh(start,-Vec(0,terrain.box.h(),0),terrain,NULL,NULL,&matrix.pos,&hit_face,&hit_mshb,&hit_mesh)) // cast a ray down-wards and store contact info { Mshb &mshb=terrain.mesh(hit_mesh).base(hit_mshb); // this is the Mshb that we've hit Vec &nrm =((hit_face&SIGN_BIT) ? mshb.quad.nrm[hit_face^SIGN_BIT] : mshb.tri.nrm[hit_face]); // this is the face normal that we've hit matrix.orn*=Matrix3().setUp(nrm); // transform our grass matrix according to surface normal matrix.pos.y-=0.05; // move it down a little } } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button UpdateGrassAndLeafs(); // update grass bending return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SHD_MAP: case RM_SOLID : terrain.draw(MatrixIdentity); // render terrain grass.draw(grass_elm,ELMS(grass_elm)); // render grass break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Grass.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain ; // terrain mesh Mesh grass ; // grass mesh Vec pos[600]; // grass positions /******************************************************************************/ void InitPre() { App.name("Grass"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3).shdMapSize(1024).shdSoft(1); ViewportFull.range=30; } /******************************************************************************/ Bool Init() { Cam.dist =6; Cam.pitch=-1; Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")); // load terrain mesh terrain.load("obj/terrain/0.mshg"); // create grass mesh grass.create(1).base(0).createGrass(48); grass.setMaterial(Materials("mtrl/grass/blade.mtrl")).setRender().setBox(); // set random positions on terrain surface REPA(pos)PosPointMeshY(Random(terrain.box).xz()*0.4,terrain,&pos[i]); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button UpdateGrassAndLeafs(); // update grass bending return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SHD_MAP: case RM_SOLID : REPA(pos)grass .draw(Matrix(0.25,pos[i])); terrain.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Separate parts rendering 1.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh mesh; Matrix matrix; /******************************************************************************/ void InitPre() { App.name("Separate parts rendering"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600); Cam.dist=3; } /******************************************************************************/ Bool Init() { mesh.create(3); // create mesh with room for 3 parts // setup #0 { MeshPart &part=mesh.part(0); part.base.create(Ball(0.7),VTX_TX0|VTX_NRM|VTX_TNG); // create Mshb part.setMaterial(Materials("mtrl/brick/0.mtrl")); // set material Set(part.name,"ball"); // set name } // setup #1 { MeshPart &part=mesh.part(1); part.base.create(Tube(0.3,3),VTX_TX0|VTX_NRM|VTX_TNG); // create Mshb part.setMaterial(Materials("mtrl/glass/0.mtrl")); // set material Set(part.name,"tube"); // set name } // setup #2 { MeshPart &part=mesh.part(2); part.base.create(Box(3,0.3,0.3),VTX_TX0|VTX_NRM|VTX_TNG); // create Mshb part.setMaterial(Materials("mtrl/grass/0.mtrl")); // set material Set(part.name,"box"); // set name } mesh.setRender().setBox(); // setup mesh rendering version and bounding box matrix.setPos(Vec(0,0,1)); // setup object matrix with position (0,0,1) return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01f,10,CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT)); return true; } /******************************************************************************/ void Draw() { D.clear(); LightDir(Cam.matrix.z).set(); if(!Kb.b(KB_SPACE)) // if space not pressed { mesh.draw(matrix); // render all parts with one object matrix }else { // when space pressed render each part separately with different matrix { CChar8 *name[]= { "tube", "box", }; mesh.showAll().hide(name,ELMS(name)).draw(matrix); // render all parts EXCEPT those listed in 'names' } { Matrix local_transformation; local_transformation.setRotateX(Tm.time()/2); mesh.hideAll().show("tube").draw(local_transformation*matrix); // render ONLY those parts that are named "tube" } { Matrix local_transformation; local_transformation.setRotateZ(Tm.time()/2); mesh.hideAll().show("box").draw(local_transformation*matrix); // render ONLY those parts that are named "box" } mesh.showAll(); // remember to un-hide all elements after separate parts rendering } D.text(0,0.8,"Hold space to render each part with different matrix"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Separate parts rendering 2 - Skeleton.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh *mesh; Skeleton *skel; Flt rifle_angle=0, turret_angle=0; /******************************************************************************/ void InitPre() { App.name("Separate parts rendering"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).ambPower(0.5); Cam.dist=3; } /******************************************************************************/ Bool Init() { mesh=Meshs ("Obj/vehicle/tank/0.mesh"); skel=Skeletons("Obj/vehicle/tank/0.skel"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01f,10,CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT)); rifle_angle+=(Kb.b(KB_S)-Kb.b(KB_W))*Tm.d(); Clamp(rifle_angle,-0.5,0.1); turret_angle+=(Kb.b(KB_E)-Kb.b(KB_Q))*Tm.d(); return true; } /******************************************************************************/ void DrawTank(Matrix &world_matrix) { // access skeleton bones OrientP &rifle =skel->getBone("rifle" ); OrientP &turret=skel->getBone("turret"); // set local transformations Matrix rifle_transform; rifle_transform.setTransformAtPos(rifle .pos,Matrix3().setRotateX( rifle_angle)); Matrix turret_transform; turret_transform.setTransformAtPos(turret.pos,Matrix3().setRotateY(turret_angle)); // convert local transformations to global matrixes (which is equal to 'local transformation' * 'parent matrix') Matrix turret_matrix=turret_transform* world_matrix, rifle_matrix= rifle_transform*turret_matrix; // draw the mesh parts separately mesh->hideAll().show("rifle" ).draw( rifle_matrix); mesh->hideAll().show("turret").draw(turret_matrix); mesh->hideAll().show("hull" ).draw( world_matrix); mesh->showAll(); } /******************************************************************************/ void Draw() { D.clear(0xFF6080FF); LightDir(Cam.matrix.z).set(); DrawTank(MatrixIdentity); D.text(0,0.9,S+ "Rifle Angle : "+ rifle_angle+" (W/S to change)"); D.text(0,0.8,S+"Turret Angle : "+turret_angle+" (Q/E to change)"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Separate parts rendering 3 - Controlled Skeleton.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** In this tutorial we'll render separate parts with matrixes automatically calculated by Controlled Skeleton CSkeleton will handle transforming child matrixes by parent matrixes All we need to do is: 1. Create CSkeleton on the base of the object's Skeleton 2. Animate the CSkeleton 3. Render the parts using CSkeleton bone matrixes As for animating the CSkeleton we'll use CSkelBone's relative rotation - CSkelBone::rot which is an 'AxisRoll' object AxisRoll contains of: struct AxisRoll { Vec axis; Flt roll; }; Where 'axis' direction determines the axis of rotation 'axis' length determines how much we'll rotate the object around 'axis' direction 'roll' is an additional parameter, which determines the angle of rotation around original bone direction AxisRoll members when calling CSkeleton::clear() are reset {axis=Vec(0,0,0); roll=0;} After reseting the members we'll adjust their values according to our desired angles /******************************************************************************/ Mesh *mesh; Skeleton *skel; CSkeleton cskel; Flt rifle_angle=0, turret_angle=0; /******************************************************************************/ void InitPre() { App.name("Separate parts rendering"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.mode(800,600).ambPower(0.5); Cam.dist=3; } /******************************************************************************/ Bool Init() { mesh=Meshs ("Obj/vehicle/tank/0.mesh"); skel=Skeletons("Obj/vehicle/tank/0.skel"); cskel.create(*skel); // create a controlled skeleton return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ void AnimateTank(Matrix &world_matrix) // animate the tank skeleton { cskel.clear(); // reset the rotation values cskel.getBone("rifle" ).rot.axis.x+= rifle_angle; // adjust rotation in X axis by 'rifle_angle' cskel.getBone("turret").rot.roll +=turret_angle; // adjust rotation around bone's original direction by 'turret_angle' cskel.updateMatrix(world_matrix); // calculate the final matrixes } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01f,10,CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT)); rifle_angle+=(Kb.b(KB_S)-Kb.b(KB_W))*Tm.d(); Clamp(rifle_angle,-0.5,0.1); turret_angle+=(Kb.b(KB_E)-Kb.b(KB_Q))*Tm.d(); AnimateTank(MatrixIdentity); return true; } /******************************************************************************/ void DrawTank() { // draw the mesh parts separately // use calculated skeleton bone transformation matrixes mesh->hideAll().show("rifle" ).draw(cskel.getBone("rifle" ).matrix()); mesh->hideAll().show("turret").draw(cskel.getBone("turret").matrix()); mesh->hideAll().show("hull" ).draw(cskel. matrix()); mesh->showAll(); } /******************************************************************************/ void Draw() { D.clear(0xFF6080FF); LightDir(Cam.matrix.z).set(); DrawTank(); D.text(0,0.9,S+ "Rifle Angle : "+ rifle_angle+" (W/S to change)"); D.text(0,0.8,S+"Turret Angle : "+turret_angle+" (Q/E to change)"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Terrain.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Gfx ground; MeshGroup mshg ; // here MeshGroup is used instead of a Mesh (single mesh) /******************************************************************************/ void InitPre() { App.name("Terrain"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3).shdSoft(1); ViewportFull.range=40; } /******************************************************************************/ void CreateMesh(Mesh &mesh) { // create random terrain heightmap Gfx gfx(128,128,1,GFX_I8,GFX_SOFT); REPD(y,gfx.y()) REPD(x,gfx.x())gfx.pixel(x,y,Random(256)); // software images don't need to be locked/unlocked gfx.blur(5,false); // apply gaussian blur to the heightmap with 5 pixel range and no clamping // create terrain Mesh mesh.create(1).base(0).createPlane(128,128,VTX_TX0); // create 2D plane with 128x128 vertexes mesh.base(0).texScale(Vec2(16)); // scale texture coordinates mesh.base(0).displaceZ(gfx); // displace vertexes Z position from heightmap mesh.transform(Matrix().setPos(Vec(-0.5,-0.6,-0.5)).rotateX(PI_2).scale(Vec(50,8,50))); // transform by matrix mesh.setNormals(); // recalculate normals mesh.setMaterial(Materials("mtrl/grass/0.mtrl")); // set material mesh.setBox(); // set bounding box } /******************************************************************************/ Bool Init() { Cam.at.y+=2; // move camera up Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")); // create mesh Mesh mesh; CreateMesh(mesh); // create terrain MeshGroup from standard Mesh mshg.create(mesh,VecI(5,1,5)); // create MeshGroup with 5x1x5 (5*1*5=25) splits (Mesh is splitted to 25 parts along axises) mshg.setRender(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01f,10,CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT)); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: mshg.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); if(Kb.b(KB_SPACE))REPA(mshg)mshg.mesh(i).box.draw(); // draw mesh bounding boxes } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\3 - Mesh\Mesh\Tree.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Mesh tree; // tree mesh /******************************************************************************/ void InitPre() { App.name("Tree"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.3); } /******************************************************************************/ Bool Init() { Cam.dist=14; Cam.at.set(0,8,0); Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button if(Kb.bp(KB_TAB))D.ambMode(!D.ambMode()); // toggle ambient occlusion on tab pressed if(Kb.bp(KB_SPACE)) { // create the tree Memb<Material*> leaf_materials; // container of leaf materials leaf_materials.New()=Materials("mtrl/leaf/0/0.mtrl"); leaf_materials.New()=Materials("mtrl/leaf/0/1.mtrl"); tree.createTree(Materials("mtrl/bark/0.mtrl"),leaf_materials) .setRender (); } UpdateGrassAndLeafs(); // call this to update wind bending return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: tree.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to create a tree"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Demos\Auto Depth of Field.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Bool ray_hit ; // if testing ray hit anything Vec ray_hit_pos; // if hit, then this is the hit position Material *brick, *glass; Mesh mbox , mball, mcapsule; struct Object // object { Actor actor; // actor Mesh *mesh ; // mesh void draw() // draw { if(mesh)mesh->draw(actor.matrix()); } }; Memb<Object> obj; // objects /******************************************************************************/ void InitPre() { App.name("Auto Depth of Field"); App.flag=APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.full(true).sync(true); ViewportFull.range=32; Ms.hide(); // set initial depth of field parameters D.dof(DOF_HIGH,1, 1,0,6); } /******************************************************************************/ Bool Init() { Physics.create(); // get materials brick=Materials("../data/mtrl/brick/0.mtrl"); glass=Materials("../data/mtrl/glass/0.mtrl"); // shapes used for mesh and actor creation Box box (32,1,32); Ball ball(0.5); Capsule capsule(0.3,2); // create meshes mbox .create(1).base(0).create(box ,VTX_TX0|VTX_NRM|VTX_TNG).texScale(Vec2(16)); mball .create(1).base(0).create(ball ,VTX_TX0|VTX_NRM|VTX_TNG); mcapsule.create(1).base(0).create(capsule,VTX_TX0|VTX_NRM|VTX_TNG); // set mesh materials, rendering versions and bounding boxes mbox .setMaterial(brick).setRender().setBox(); mball .setMaterial(glass).setRender().setBox(); mcapsule.setMaterial(brick).setRender().setBox(); // create objects { // ground { Object &o=obj.New(); o.mesh=&mbox; o.actor.create(box,0).pos(Vec(0,-box.h()/2,0)); } // pillars REPD(x,16) REPD(z,16) { Object &o=obj.New(); o.mesh=&mcapsule; o.actor.create(capsule,0).pos(Vec(box.lerpX(x/15.0),capsule.h/2-capsule.r,box.lerpZ(z/15.0))); } // balls REP(100) { Object &o=obj.New(); o.mesh=&mball; o.actor.create(ball).pos(Vec(box.lerpX(RandomF()),ball.r+capsule.h,box.lerpZ(RandomF()))); } } // set initial camera Cam.setAngle(Vec(0,2,0),0,-0.2).set(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Physics.sim().get(); // update camera { if(Kb.b(KB_A ))Cam.matrix.pos-=Cam.matrix.x*Tm.d(); if(Kb.b(KB_D ))Cam.matrix.pos+=Cam.matrix.x*Tm.d(); if(Kb.b(KB_W ))Cam.matrix.pos+=Cam.matrix.z*Tm.d(); if(Kb.b(KB_S ))Cam.matrix.pos-=Cam.matrix.z*Tm.d(); if(Kb.b(KB_SPACE))Cam.matrix.pos+=Cam.matrix.y*Tm.d(); if(Kb.b(KB_LCTRL))Cam.matrix.pos-=Cam.matrix.y*Tm.d(); if(Ms.hidden()) { Cam.yaw -=Ms.dir_d.x; Cam.pitch+=Ms.dir_d.y; } Cam.setAngle(Cam.matrix.pos,Cam.yaw,Cam.pitch).updateVelocities().set(); } // toggle mouse if(Kb.bp(KB_TAB))Ms.toggle(); // test ray { Flt new_z; // new Z focus PhysHit phys_hit; Vec pos,dir; if(Ms.hidden()) { pos=Cam.matrix.pos; dir=Cam.matrix.z; }else { ScreenToPosDir(Ms.pos,pos,dir); } if(Physics.ray(pos,dir*Viewport.range,&phys_hit)) // cast a ray from camera and check if it hits something { ray_hit =true; ray_hit_pos=phys_hit.plane.p; new_z =phys_hit.dist; //set new z focus to ray hit distance }else { ray_hit=false; new_z =Viewport.range; // set new z focus to viewport range } // set new depth of field z focus D.dofZ(LerpTime(D.dofZ(),new_z,0.001)); } return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID: REPAO(obj).draw(); break; case RM_LIGHT: LightDir(!Vec(1,-1,1)).add(); break; } } void Draw() { Renderer(Render); if(ray_hit) { SetMatrix(); Ball(0.1,ray_hit_pos).draw(); } D.text(0,0.9,"Press Tab to toggle mouse, WSAD+Space+Control to move camera"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Demos\Day Night Cycle.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ MeshGroup terrain; // terrain mesh Flt hour ; // current hour /******************************************************************************/ void InitPre() { App.name("Nature"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.2).hpRt(true).shdSoft(1).shdMapSize(1024); } /******************************************************************************/ Bool Init() { Cam.dist=6; Cam.at.set(0,2,0); Sky .set(); Suns.New().set(*Gfxs("gfx/sky/sun.gfx")).rays.mode=SUN_RAYS_HIGH; // load terrain mesh terrain.load("obj/terrain/0.mshg"); // set initial hour hour=5; // load clouds Clouds.layered.set(3,Gfxs("Clouds/Layers/0.gfx")); REPAO(Clouds.layered.layer).velocity*=4; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // move camera on right mouse button // update hour hour+=Tm.d()*2; // set sun position Sun &sun=Suns[0]; SinCos(sun.pos.y,sun.pos.x,hour/24*PI2-PI_2); sun.pos.z=0; sun.pos*=Matrix3().setRotateY(PI-PI_4); // tweak the sun to rise earlier, and set later sun.pos.y+=0.5; sun.pos.normalize(); // set sun color Flt power=Sat(Cbrt(sun.pos.y)); sun.light_color=power; // set sky color Vec night_color(0.02,0.04,0.10), horizon_color(0.35,0.45,0.64), sky_color(0.30,0.38,0.54); Sky.set(Lerp(night_color,horizon_color,power),sky_color*power); // update clouds Clouds.layered.update(); REP(Clouds.layered.layers())Clouds.layered.layer[i].color=ColorBrightness(power); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SHD_MAP: case RM_SOLID : terrain.draw(MatrixIdentity); // render terrain break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Hour "+(Trunc(hour)%24)); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Demos\Facial Animation.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ CSkeleton cskel; Mesh *mesh; Window window; Text text [5]; Slider slider[4]; CheckBox blink; /******************************************************************************/ void InitPre() { App.name("Facial Animation"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.2).shdMode(SHD_MAP_HW).shdSoft(1).shdMapSize(1024).hpRt(true); ViewportFull.range=8; } /******************************************************************************/ Bool Init() { // camera Cam.dist=0.4; Cam.at.set(0,0.75,0); Cam.yaw=PI; Cam.setSpherical().set(); // sun Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")); sun.pos =!Vec(1,1,3); sun.light_color=1-D.ambColor(); // sky Sky.set(); // character cskel.create("obj/chr/human/0.skel",1.8); mesh=Meshs ("obj/chr/human/0.mesh"); // gui Gui +=window .create(Rect_R(D.w(),0,0.49,0.50),"Expressions"); window+=text[0].create(Vec2(0.13,-0.05),"Angry" ); window+=slider[0].create(Rect_L(0.26,-0.05,0.2 ,0.05)); window+=text[1].create(Vec2(0.13,-0.13),"Astonished"); window+=slider[1].create(Rect_L(0.26,-0.13,0.2 ,0.05)); window+=text[2].create(Vec2(0.13,-0.21),"Sad" ); window+=slider[2].create(Rect_L(0.26,-0.21,0.2 ,0.05)); window+=text[3].create(Vec2(0.13,-0.29),"Smile" ); window+=slider[3].create(Rect_L(0.26,-0.29,0.2 ,0.05)); window+=text[4].create(Vec2(0.13,-0.37),"Blink" ); window+=blink .create(Rect_L(0.26,-0.37,0.05,0.05),true); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Gui.update(); // animate Flt time=Tm.time(); cskel.clear () .animate(L"anim/face/angry.anim" ,time,slider[0]()) .animate(L"anim/face/astonished.anim",time,slider[1]()) .animate(L"anim/face/sad.anim" ,time,slider[2]()) .animate(L"anim/face/smile.anim" ,time,slider[3]()); if(blink()) { Flt blend=Frac(time,3); // blink every 3 seconds blend/=0.1; // blink duration = 0.1 seconds if( blend>1)blend=2-blend; cskel.animate(L"anim/face/blink.anim",time,blend,true); } cskel.updateMatrix(MatrixIdentity) .updateVelocities(); if(!Gui.window_lit && Ms.b(0))CamHandle(0.01,10,CAMH_ZOOM|CAMH_ROT); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SOLID : case RM_SHD_MAP: mesh->draw(cskel); break; } } void Draw() { Renderer(Render); Gui.draw(); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Demos\Lights.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ Int lights=3 ; // number of lights (1..3) Material material ; // material light Mesh mbox , // mesh box mball , // mesh ball mlight , // mesh light mballs ; // mesh ball (shadow stencil version) Vec ball_pos[8], // ball positions light_pos[3]; // light positions /******************************************************************************/ void SetEffect() { mbox .setEffect(); mball.setEffect(); } /******************************************************************************/ void InitPre() { App.name("Lights Rendering Demo"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; PakAdd("../data/engine.pak"); D.set_effect=SetEffect; D.full(true).bumpMode(BUMP_RELIEF).shdSoft(1).shdJitter(true); } /******************************************************************************/ Bool Init() { // create materials Material *brick=Materials("../data/mtrl/brick/0.mtrl"); material.reset(); material.glow=0.6; material.ambient=1; // create meshes mbox .create(1).base(0).create( Box(1 ),VTX_TX0|VTX_NRM|VTX_TNG).reverse( ); // create mesh box , reverse it because it's meant to be viewed from inside mball .create(1).base(0).create(Ball(0.15),VTX_TX0|VTX_NRM|VTX_TNG).weldVal(VTX_POS); // create mesh ball, weld it's vertex positions (stencil shadows are very sensitive to even the smallest irregularities) mlight.create(1).base(0).create(Ball(0.04)); // set mesh materials, rendering versions and bounding boxes mbox .setMaterial( brick ).setRender().setBox(); mball .setMaterial( brick ).setRender().setBox(); mlight.setMaterial(&material).setRender().setBox(); // create stencil shadow version of ball mesh mballs.create(mball).toStencilShadow(); // set random positions REPA(ball_pos)ball_pos[i]=Random(Box(0.9)); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.01f,10,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // update light positions when space is not pressed if(!Kb.b(KB_SPACE)) { static Flt t; t+=Tm.d()/2; light_pos[0].set(0,0,0.3); light_pos[0]*=Matrix3().setRotateX(t).rotateY(t/2 ).rotateZ(t/3 ); light_pos[1].set(0,0,0.6); light_pos[1]*=Matrix3().setRotateX(t).rotateY(t/1.5).rotateZ(t/2.5); light_pos[2].set(0,0,0.5); light_pos[2]*=Matrix3().setRotateX(t).rotateY(t/1.3).rotateZ(t/3.2); } // change settings if(Kb.c('1'))lights=1; if(Kb.c('2'))lights=2; if(Kb.c('3'))lights=3; if(Kb.c('q'))D.shdMode(SHD_NONE); if(Kb.c('w'))D.shdMode(SHD_MAP ).shdSoft(0); if(Kb.c('e'))D.shdMode(SHD_MAP ).shdSoft(1); if(Kb.c('r'))D.shdMode(SHD_MAP_HW ).shdSoft(0); if(Kb.c('t'))D.shdMode(SHD_MAP_HW ).shdSoft(1); if(Kb.c('y'))D.shdMode(SHD_STENCIL).shdSoft(0); if(Kb.c('u'))D.shdMode(SHD_STENCIL).shdSoft(1); if(Kb.c('a'))D.bumpMode(BUMP_FLAT ); if(Kb.c('s'))D.bumpMode(BUMP_NORMAL ); if(Kb.c('d'))D.bumpMode(BUMP_PARALLAX); if(Kb.c('f'))D.bumpMode(BUMP_RELIEF ); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SHD_STENCIL: REPA(ball_pos)mballs.draw(Matrix(ball_pos[i])); break; case RM_EARLY_Z: case RM_SHD_MAP: case RM_SOLID : { mbox .draw(MatrixIdentity); REPA(ball_pos)mball.draw(Matrix(ball_pos[i])); if(Renderer()!=RM_SHD_MAP) // don't render light balls in shadow mapping mode - this will disable casting shadows for them { material.color.v3.set(1 ,1,0.5); material.validate(); mlight.draw(Matrix(light_pos[0])); if(lights>=2){material.color.v3.set(0.5,1,1 ); material.validate(); mlight.draw(Matrix(light_pos[1]));} if(lights>=3){material.color.v3.set(0.5,1,0.5); material.validate(); mlight.draw(Matrix(light_pos[2]));} } }break; case RM_LIGHT: { REP(lights)mlight.draw(Matrix(light_pos[i])); switch(lights) { case 1: LightPoint(0.50,light_pos[0],Vec(1)).add(); break; case 2: LightPoint(0.45,light_pos[0],Vec(1,0.5,0.0)).add(); LightPoint(0.45,light_pos[1],Vec(0,0.5,1.0)).add(); break; case 3: LightPoint(0.40,light_pos[0],Vec(1 ,0.3,0.0)).add(); LightPoint(0.40,light_pos[1],Vec(0.0,0.3,1 )).add(); LightPoint(0.40,light_pos[2],Vec(0.0,0.4,0.0)).add(); break; } }break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Demos\Nature.txt /******************************************************************************/ #include "stdafx.h" /******************************************************************************/ const Bool hi_quality=true; // change to false to disable hi-quality settings /******************************************************************************/ MeshGroup terrain; // terrain mesh Mesh tree[4]; // tree mesh Grass grass ; // grass renderer Grass::Elm grass_elm [hi_quality ? 5000 : 3000]; // single grass element Matrix tree_matrix[hi_quality ? 20 : 10]; // tree matrixes /******************************************************************************/ void InitPre() { App.name("Nature"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).ambPower(0.35).hwDepthBuffer(true).shdMode(SHD_MAP_HW); if(hi_quality) { D.hdr(true).hpRt(true).bumpMode(BUMP_PARALLAX).hdrExposure(0.7).bloomOverbright(true) .ambMode(AMB_LOW).ambRange(0.05).ambHalfRes(true) .shdSoft(1).shdMapSize(1024).shdJitter(true).grassShadow(true) .mtnMode(MTN_HIGH); ViewportFull.range=50; }else { D.bendLeafs(false); ViewportFull.range=35; } } /******************************************************************************/ Bool Init() { Cam.dist=6; Cam.at.set(0,2,0); Sky.set(); // set sun Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")); sun.light_color=1-D.ambColor(); sun.rays.mode =(hi_quality ? SUN_RAYS_HIGH : SUN_RAYS_LOW); // set water if(hi_quality) { Water.set (*Gfxs("gfx/water/0.gfx"),*Gfxs("gfx/water/0.n.gfx"),Gfxs("gfx/fx/reflection.gfx")); Water.plane(Water.plane()-Vec(0,0.8,0)); Water.wave_scale=0.3; } // load clouds Clouds.layered.set(3,Gfxs("Clouds/Layers/0.gfx")); // load terrain mesh terrain.load("obj/terrain/0.mshg"); // create tree meshes Memb<Material*> leaf_materials; leaf_materials.New()=Materials("mtrl/leaf/0/0.mtrl"); leaf_materials.New()=Materials("mtrl/leaf/0/1.mtrl"); REPA(tree)tree[i].createTree(Materials("mtrl/bark/0.mtrl"),leaf_materials).scale(Vec(0.5)).setRender(); // create grass renderer grass.create(); // set tree matrixes REPA(tree_matrix) { tree_matrix[i].setRotateY(RandomF(PI2)); // set matrix from random Y rotation PosPointMeshY(Random(terrain.box).xz(),terrain,&tree_matrix[i].pos); // set random position on surface tree_matrix[i].pos.y-=0.1; // move it down a little } // set random grass matrixes terrain.setFaceNormals(); // make sure terrain has face normals, since we'll need those later REPA(grass_elm) { Grass::Elm &elm =grass_elm[i]; Matrix &matrix=elm.matrix; elm.param.set(0,0,0,Random(16,128)); // set parameters matrix.setScale(Vec(0.18,0.3,0.18)).rotateY(RandomF(PI2)); // set scaled matrix and rotate it Vec start =Random(terrain.box); // set random position at top of the terrain mesh box start.y=terrain.box.max.y; I32 hit_face,hit_mshb,hit_mesh; if(SweepPointMesh(start,-Vec(0,terrain.box.h(),0),terrain,NULL,NULL,&matrix.pos,&hit_face,&hit_mshb,&hit_mesh)) // cast a ray down-wards and store contact info { Mshb &mshb=terrain.mesh(hit_mesh).base(hit_mshb); // this is the Mshb that we've hit Vec &nrm =((hit_face&SIGN_BIT) ? mshb.quad.nrm[hit_face^SIGN_BIT] : mshb.tri.nrm[hit_face]); // this is the face normal that we've hit matrix.orn *=Matrix3().setUp(nrm); // transform our grass matrix according to surface normal matrix.pos.y-=0.05; // move it down a little } } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(0)?CAMH_MOVE_XZ:(Ms.b(1)?CAMH_MOVE:CAMH_ROT))); // move camera on left/right mouse button Clouds.layered.update(); Water . update(Vec2(0.2)); UpdateGrassAndLeafs(); if(Kb.bp(KB_F10))Renderer.screenShots("ScreenShot/","bmp"); return true; } /******************************************************************************/ void Render() { switch(Renderer()) { case RM_SHD_MAP: case RM_SOLID : case RM_SOLID_M: terrain.draw(MatrixIdentity); // render terrain REPA(tree_matrix)tree[i%ELMS(tree)].draw(tree_matrix[i]); // render trees grass.draw(grass_elm,ELMS(grass_elm)); // render grass break; } } void Draw() { Renderer(Render); D.text(0,0.9,S+"Fps "+Tm.fps()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\01 - Character.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** Define your custom player character class basing on already defined Game::Chr Game::Chr is a class which handles the most basic character methods including : movement, animations, physics and actions /******************************************************************************/ struct Player : Game::Chr // extend character class by defining a player class based on the character { virtual Bool update(); // here we'll update the player (please note that this is a virtual method) }; /******************************************************************************/ Bool Player::update() { // here we update character input according to mouse and keyboard // before we set the input, we need to check if the character isn't controlled by an automatic action if(action) { // if it's controlled by an action we leave the input with no changes, // however we can optionally break that action, by pressing for example movement keys if(Kb.b(KB_W) || Kb.b(KB_S) || Kb.b(KB_A) || Kb.b(KB_D) || Kb.b(KB_Q) || Kb.b(KB_E))actionBreak(); } if(!action) // if the character isn't controlled by an automatic action, we can set the input { // turn & move input.anglei.x=Kb.b(KB_Q)-Kb.b(KB_E); input.anglei.y=Kb.b(KB_T)-Kb.b(KB_G); input.diri .x=Kb.b(KB_D)-Kb.b(KB_A); input.diri .z=Kb.b(KB_W)-Kb.b(KB_S); input.diri .y=Kb.b(KB_SPACE)-Kb.b(KB_LSHIFT); // dodge, crouch, walk, jump input.dodge = Kb.bd(KB_D)-Kb.bd(KB_A); input.crouch= Kb.b (KB_LSHIFT); input.walk = Kb.b (KB_LCTRL ); input.jump =(Kb.bp(KB_SPACE) ? 3.5 : 0); // mouse turn Flt max=DegToRad(900)*Tm.d(), dx =Ms.dir_ds.x*1.7, dy =Ms.dir_ds.y*1.7*Ms.inv(); angle.x-=Mid(dx,-max,max); angle.y+=Mid(dy,-max,max); // ready stance change ready^=Kb.bp(KB_R); } return __super::update(); // call Game::Chr::update on which Player is based on } /******************************************************************************/ Actor ground; // ground actor Player player; // player /******************************************************************************/ void InitPre() { App.name("Game Character"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true); Cam.dist=5; } /******************************************************************************/ Bool Init() { Physics.create(); ground .create(Box(15,1,15,Vec(0,-2,0)),0); player.create(0.45, 1.8, Vec(0,0,0), *Meshs("obj/chr/human/0.mesh"), *Skeletons("obj/chr/human/0.skel"), 1.8); // create player by radius, height, position, mesh, skeleton and mesh/skeleton scale return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Physics.sim().get(); player.update(); // update player Cam.setSpherical(player.ctrl.actor.pos()+Vec(0,1,0),player.angle.x,player.angle.y,0,Cam.dist*ScaleFactor(Ms.wheel*-0.2)).updateVelocities().set(); // update camera according to player angles and mouse wheel return true; } /******************************************************************************/ void Draw() { D.clear(); LightDir(Cam.matrix.z).set(); ground.draw(); // draw ground actor player.draw(); // draw player } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\02 - World.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** When writing applications with worlds, you need to additionaly include all the Headers generated by the World Editor these Headers are stored in the "enum/_enums.h" file in your Game Data folder for more information about Enums and Headers please check World Editor documentation /******************************************************************************/ #include "../../../../../data/enum/_enums.h" /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; // container for static objects Game::ObjMemx<Game::Item > Items; // container for item objects Game::ObjMemx<Game::Chr > Chrs; // container for character objects /******************************************************************************/ void InitPre() { App.name("World Manager"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024); Cam.dist =10; Cam.yaw =-PI_4; Cam.pitch=-0.5; Cam.at.set(16,0,16); } /******************************************************************************/ Bool Init() { Physics.create(); Game::World.init(); // initialize world, optionally you can change default parameters here // once the world is initialized, we need to tell the world 'which class handles which type' // this is done by assigning memory containers to certain Object Types defined in Game Enums (which were used in the World Editor) Game::World.setType(Statics,OBJ_STATIC) // set 'Statics' memory container for 'OBJ_STATIC' objects .setType(Items ,OBJ_ITEM ) // set 'Items' memory container for 'OBJ_ITEM' objects .setType(Chrs ,OBJ_CHR ); // set 'Chrs' ' memory container for 'OBJ_CHR' objects // now when the engine is set up properly we can start a 'new game' with a builded world Game::World.New("world/sample"); // create the world by giving path to builded world // when the world is loaded it doesn't actually load all the terrain and objects into memory // it loads only information about them // you need to tell the world which terrain and objects you need to use at the moment // to do that call: Game::World.update(Cam.at); // which updates world to use only terrain and objects at given position, here camera position is used return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); // update the world to given position return true; } /******************************************************************************/ void Render() { Game::World.draw(); // draw world (this is done outside of 'switch(Renderer())' because world automatically detects active rendering mode) switch(Renderer()) { case RM_LIGHT: LightDir(!Vec(1,-1,1)).add(); break; } } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\03 - World with Character.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** In this tutorial is presented how to combine extending base classes with World Manager usage /******************************************************************************/ struct Player : Game::Chr // extend character structure by defining a player class based on the character { Memx<Game::Item> item; // here is the characters inventory, a container of items virtual _Memx* itemContainer(){return &item;} // override default method of character, to return proper item container void updateItems(); // update items actions virtual Bool update (); // here we'll update the player }; /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; // container for static objects Game::ObjMemx<Game::Item > Items ; // container for item objects Game::ObjMemx< Player> Players; // container for player objects /******************************************************************************/ void Player::updateItems() { if(Kb.bp(KB_1)) // try to pickup an item if(Items.elms()) // if world items container has some elements itemPickUp(Items[0]); // pick up the first valid item if(Kb.bp(KB_2)) // try to drop down an item if(item.elms()) // if inventory has some items itemDropDown(item[0]); // drop down the first item if(!Kb.alt)grabStop();else // if don't want to grab { if(grab.is()) // if already grabbing { Vec pos; SinCos(pos.z,pos.x,angle.x+PI_2); // set direction according to player angle pos *=ctrl.radius()+0.5; // set radius according to player controller radius pos.y=ctrl.height()*0.4; // set vertical position pos +=T.pos(); grab.pos(pos); // set desired grab position }else if(Items.elms()) // if isn't grabbing anything check for presence of world items { grabStart(Items[0]); // grab first present } } } /******************************************************************************/ Bool Player::update() { if(action) { if(Kb.b(KB_W) || Kb.b(KB_S) || Kb.b(KB_A) || Kb.b(KB_D) || Kb.b(KB_Q) || Kb.b(KB_E))actionBreak(); } if(!action) { // turn & move input.anglei.x=Kb.b(KB_Q)-Kb.b(KB_E); input.anglei.y=Kb.b(KB_T)-Kb.b(KB_G); input.diri .x=Kb.b(KB_D)-Kb.b(KB_A); input.diri .z=Kb.b(KB_W)-Kb.b(KB_S); input.diri .y=Kb.b(KB_SPACE)-Kb.b(KB_LSHIFT); // dodge, crouch, walk, jump input.dodge = Kb.bd(KB_D)-Kb.bd(KB_A); input.crouch= Kb.b (KB_LSHIFT); input.walk = Kb.b (KB_LCTRL ); input.jump =(Kb.bp(KB_SPACE ) ? 3.5 : 0); // mouse turn Flt max=DegToRad(900)*Tm.d(), dx =Ms.dir_ds.x*1.7, dy =Ms.dir_ds.y*1.7*Ms.inv(); angle.x-=Mid(dx,-max,max); angle.y+=Mid(dy,-max,max); // ready stance change ready^=Kb.bp(KB_R); } updateItems(); return __super::update(); } /******************************************************************************/ void InitPre() { App.name("World with Character"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024); } /******************************************************************************/ Bool Init() { Text_ds.scale*=0.8; Physics.create(); // create the world Game::World.init() .setType(Statics,OBJ_STATIC) .setType(Players,OBJ_CHR ) // please note that here we'll use 'Players' memory container for 'OBJ_CHR' objects .setItem(Items ,OBJ_ITEM ) // please note that here is called 'setItem' instead of 'setType', this is used for enabling built-in character<->item relations such as picking up and dropping items .New("world/sample" ); Cam.setSpherical(Vec(16,0,16),-PI_4,-0.5,0,10).set(); // set initial camera return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); // update world to given position return true; } /******************************************************************************/ void Render() { Game::World.draw(); switch(Renderer()) { case RM_LIGHT: LightDir(!Vec(1,-1,1)).add(); break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press WSAD keys to move, 1/2 to pick up/drop item, Alt to grab"); if(Players.elms())D.text(0,0.8,S+"Items in inventory : "+Players[0].item.elms()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\04 - Lights.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** In this tutorial is presented how to use lighting created in World Editor Here 2 light sources are used: 1st is a static light defined in a constant position in the World Editor 2nd is a light stored in a candle object, as a sub-object /******************************************************************************/ struct Item : Game::Item // extend game items { Game::LightPoint light_point; // point light virtual void create(Game::ObjParams &obj); // extend creation virtual void draw ( ); // extend drawing virtual void save (File &f); // extend saving virtual Bool load (File &f); // extend loading }; /******************************************************************************/ void Item::create(Game::ObjParams &obj) { __super::create(obj); // default create // add custom children for(Game::ObjParams *cur=&obj; cur; cur=cur->base()) // check 'obj' and all its bases FREPA(cur->sub_obj) // for each sub-object in 'cur' { Game::ObjParams &o=cur->sub_obj[i]; switch(Game::World.objType(o.type())) // check the type of sub-object { case OBJ_LGT_PNT: // if its light, then create our member from its parameters light_point.create(o); break; } } } /******************************************************************************/ void Item::draw() { if(0) // optionally you can disable shadow casting of the item, when the item is the light source { if(Renderer()==RM_SHD_MAP && CurrentLight.src==&light_point)return; // if in shadowing mode and current light source is 'light_point' then don't draw anything } __super :: draw( ); // default draw light_point.draw(actor.matrix()); // draw light with item's matrix } /******************************************************************************/ void Item::save(File &f) { __super::save(f); // save default data light_point.save(f); // save point light } Bool Item::load(File &f) { if(__super::load(f)) // load default data { light_point.load(f); // load point light return true; } return false; } /******************************************************************************/ Game::ObjMemx<Item > Items; Game::ObjMemx<Game::LightPoint> LightPoints; // container for point light objects /******************************************************************************/ void InitPre() { App.name("Lights"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024); Cam.dist =10; Cam.yaw =-PI_4; Cam.pitch=-0.5; Cam.at.set(16,0,16); } /******************************************************************************/ Bool Init() { Physics.create(); Game::World.init ( ) .setType(Items ,OBJ_ITEM ) .setType(LightPoints,OBJ_LGT_PNT) .New ("world/lights" ) .update (Cam.at ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\05 - Saving and Loading.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** In this tutorial is presented how to save and load World states /******************************************************************************/ Game::ObjMemx<Game::Item> Items; /******************************************************************************/ void InitPre() { App.name("Lights"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); Cam.dist =10; Cam.yaw =-PI_4; Cam.pitch=-0.5; Cam.at.set(16,0,16); } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set(); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.pos.set(0,1,0); Game::World.init ( ) .setType(Items,OBJ_ITEM ) .New ("world/barrels") .update (Cam.at ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); if(Kb.bp(KB_F2))Game::World.save("LocalData/save.sav"); // save game if(Kb.bp(KB_F3))Game::World.load("LocalData/save.sav"); // load game Game::World.update(Cam.at); // add some velocity to objects if(Kb.bp(KB_SPACE))REPA(Items)Items[i].actor.addVel(5*Random.dir(Vec(0,1,0),0.7)); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.9,"Press F2 to save and F3 to load"); D.text(0,0.8,"Press Space to add velocity"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\06 - Pathfind.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ Game::ObjMemx<Game::Chr > Chrs ; Game::ObjMemx<Game::Static> Statics; Marker marker; // marker pointing character destination target /******************************************************************************/ void InitPre() { App.name("Pathfind"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=50; Cam.dist = 10; Cam.yaw =-PI_4; Cam.pitch=-PI_3; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); Game::World.init ( ) .setType(Chrs ,OBJ_CHR ) .setType(Statics,OBJ_STATIC) .New ("world/path" ) .update (Cam.at ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); // move player if(Ms.bp(0) && Chrs.elms()) // on LMB pressed { Vec pos,dir ; ScreenToPosDir(Ms.pos,pos,dir); // convert screen mouse position to world position and direction PhysHit phys_hit; if(Physics.ray(pos,dir*Viewport.range,&phys_hit)) // if ray-test hit something { Chrs[0].actionMoveTo(phys_hit.plane.p); // order character to move to that location marker.color=YELLOW; marker.size=2; marker.range_opaque=0.1; marker.range_fade =0.2; marker.gfx=Gfxs("gfx/particle/star.gfx"); marker.local_matrix.setPosDir(phys_hit.plane.p,Vec(0,1,0)); } } // rotate camera if(Ms.b(1)) { Cam.yaw -=Ms.dir_d.x; Cam.pitch+=Ms.dir_d.y; } Cam.setSpherical(Chrs[0].pos(),Cam.yaw,Cam.pitch,0,Cam.dist*ScaleFactor(Ms.wheel*-0.2)).updateVelocities().set(); // rotate marker around its z axis marker.local_matrix.orn.rotateZVec(Tm.d()); return true; } /******************************************************************************/ void Render() { Game::World.draw(); switch(Renderer()) { case RM_BLEND: if(Chrs[0].action==Game::ACTION_MOVE_TO)marker.draw(MatrixIdentity); break; } } void Draw() { Renderer(Render); // show blocked places if(Kb.b(KB_SPACE)) // if space pressed if(Chrs.elms()) // if at least one character is available { Vec pos =Chrs[0].pos(); // get character position VecI2 area_pos=Game::World.worldToAreaPos(pos); // convert from world position to area coordinates if(const Game::Area::Path *path=Game::World.pathGet(area_pos)) // if found paths at given coordinates { D.clearZ (); // clear Z Buffer SetMatrix(); // reset drawing matrix Vec world_pos=Game::World.areaToWorldPos(area_pos).x0y(); // convert 2D Area Coordinates to 3D World Position Flt cell_size=(1.0f/AREA_PATH_RES)*Game::World.areaSize(); // get size of a single path cell VI.color(ColorAlpha(RED,0.5f)); // set drawing color to transparent RED REPD(y,AREA_PATH_RES) REPD(x,AREA_PATH_RES)if(!path->walkable(x,y)) // if current cell isn't walkable { Vec pos=world_pos+Vec(x,0,y)*cell_size; // get world position of a single path cell VI.quad(pos+Vec( 0,0,cell_size), // draw a quad which extends 'pos' to right and forward by 'cell_size' pos+Vec(cell_size,0,cell_size), pos+Vec(cell_size,0, 0), pos+Vec( 0,0, 0)); } VI.end(); } } // informations D.text(0,0.9,"Press LMB to move player, RMB to rotate camera"); D.text(0,0.8,"Press Space to show blocked places at character position"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\07 - Doors.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct Door : Game::Door // extend doors { virtual void draw(); // extend default drawing, we'll use it to enable door highlighting }; struct Chr : Game::Chr // extend characters { virtual Bool update(); // extend default updating, we'll use it to detect if when moving there are some closed doors which we'll open automatically }; /******************************************************************************/ Game::ObjMemx< Chr > Chrs ; Game::ObjMemx< Door > Doors ; // container for door objects Game::ObjMemx<Game::Static> Statics; Game::Obj *Object; // game object under mouse cursor /******************************************************************************/ void Door::draw() // extended door drawing { if(Object==this && Renderer()==RM_SOLID)SetHighlight(ARGB(0,30,30,30)); // if the objects is the one under cursor, enable highlight before drawing it __super::draw(); // default draw if(Renderer()==RM_SOLID)SetHighlight(); // clear highlight to zero } /******************************************************************************/ Bool Chr::update() // extended character updating { if(__super::update()) { // we wan't to detect if a player is moving to a destination path, and if on its way there is a closed door if(action==Game::ACTION_MOVE_TO) // if we're in automatic action move to { // setup movement direction Vec dir; dir.y=0; SinCos(dir.z,dir.x,angle.x+PI_2); // 'dir' is the direction where the player is moving at the moment // setup a ball at characters position Ball ball(ctrl.radius(),pos()); // sweep for an obstacle PhysHit phys_hit; if(Physics.sweep(ball,dir,&phys_hit,IndexToFlag(Game::GROUP_DOOR))) // test for obstacles in 1 meter range, test door actor groups only if(Door *door=CAST(Door,phys_hit.obj)) // if it's actually a door { door->open(); // automatically open the door } } return true; } return false; } /******************************************************************************/ void InitPre() { App.name("Doors"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=50; Cam.dist = 10; Cam.yaw =-PI_4; Cam.pitch=-PI_3; } /******************************************************************************/ Bool Init() { Text_ds.scale*=0.8; Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); Game::World.init ( ) .setType(Chrs ,OBJ_CHR ) .setType(Doors ,OBJ_DOOR ) .setType(Statics,OBJ_STATIC) .New ("world/door" ) .update (Cam.at ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); // detect object under cursor Vec pos,dir ; ScreenToPosDir(Ms.pos,pos,dir); // convert screen mouse position to world position and direction PhysHit phys_hit; if(Physics.ray(pos,dir*Viewport.range,&phys_hit)) // if ray-test hit something { Object=phys_hit.obj; // get encountered object if(Ms.bp(0)) // if LMB is pressed { if(Door *door=CAST(Door,Object)) // if current object is of 'Door' type { door->toggle(); // toggle door } else // if not then move to that position { if(Chrs.elms())Chrs[0].actionMoveTo(phys_hit.plane.p); } } }else { Object=NULL; // clear object pointer } // rotate camera if(Ms.b(1)) { Cam.yaw -=Ms.dir_d.x; Cam.pitch+=Ms.dir_d.y; } if(Chrs.elms())Cam.setSpherical(Chrs[0].pos(),Cam.yaw,Cam.pitch,0,Cam.dist*ScaleFactor(Ms.wheel*-0.2)).updateVelocities().set(); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.92,"Press LMB on the door to open or close it"); D.text(0,0.84,"Press LMB on the ground to move the player"); D.text(0,0.76,"Press RMB to rotate the camera"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\08 - Custom Parameters.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ // ITEM /******************************************************************************/ struct Item : Game::Item // extend items { Char name[64]; // add new parameter 'name' I32 value ; // add new parameter 'value' virtual void create(Game::ObjParams &obj); // extend default creation // since new parameters are declared we need to properly initialize them in constructor, and save/load them in IO methods: // constructor Item(); // io methods virtual void save(File &f); virtual Bool load(File &f); }; /******************************************************************************/ void Item::create(Game::ObjParams &obj) { __super::create(obj); // default create // now setup custom parameters from 'obj' if(Game::Param *par=obj.findParam("name" ))Set(name ,par->asStr()); if(Game::Param *par=obj.findParam("value")) value=par->asInt() ; } /******************************************************************************/ Item::Item() { name[0]=0; value=0; } /******************************************************************************/ void Item::save(File &f) { __super::save(f); // default save f<<name<<value; // save custom parameters } Bool Item::load(File &f) { if(__super::load(f)) // if default load was successful { f>>name>>value; // load custom parameters return true; // return success } return false; // return failure } /******************************************************************************/ // MAIN /******************************************************************************/ Game::ObjMemx<Item> Items; /******************************************************************************/ void InitPre() { App.name("Custom Parameters"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=50; Cam.at.set(16,0,16); Cam.dist = 10; Cam.pitch=-PI_3; } /******************************************************************************/ Bool Init() { Text_ds.scale*=0.8; Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); Game::World.init ( ) .setItem(Items,OBJ_ITEM ) .New ("world/custom params"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); // draw item parameters REPA(Items) { Item &item =Items[i]; // get i-th Items Vec2 screen=PosToScreen(item.pos()); // convert world position to screen position D.text(screen,item.name); // draw item's name } } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\09 - Extending Game Object Class.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** In this tutorial is presented how to extend a Game Object class. But unlike in previous examples, we won't base on Character/Item or other classes. This time we'll extend the most base class - Game::Obj. /******************************************************************************/ struct NewObj : Game::Obj // extend Game Object { Vec position; // the class will contain only position // provide necessary methods required by Game::Obj : virtual void create(Game::ObjParams &obj); // extend default creation virtual Vec pos( ){return position ;} // get position virtual void pos(Vec &pos){ T.position=pos;} // set position virtual Matrix matrix( ){return position ;} // get matrix virtual void matrix(Matrix &matrix){ T.position=matrix.pos;} // set matrix virtual Bool update(){return true;} // object update virtual void draw (); // object draw virtual void disable(){} virtual void enable(){} // constructor NewObj(); // io methods virtual void save(File &f); virtual Bool load(File &f); }; /******************************************************************************/ NewObj::NewObj() // initialize values in constructor { position.zero(); } void NewObj::create(Game::ObjParams &obj) { // now setup custom parameters from 'obj' position=obj.matrixFinal().pos; // obtain our 'position' member from 'obj' } /******************************************************************************/ void NewObj::draw() { switch(Renderer()) { case RM_SOLID: case RM_LIGHT: { SetMatrix(); Ball(1,position).draw(ARGB(0,255,255,255)); // draw white ball at objects position }break; } } /******************************************************************************/ void NewObj::save(File &f) { __super::save(f); // default save f<<position; // save custom parameters } Bool NewObj::load(File &f) { if(__super::load(f)) // if default load was successful { f>>position; // load custom parameters return true; // return success } return false; // return failure } /******************************************************************************/ // MAIN /******************************************************************************/ Game::ObjMemx<NewObj> NewObjs; // container for objects /******************************************************************************/ void InitPre() { App.name("Game::Obj class"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=50; Cam.at.set(16,0,16); Cam.dist = 10; Cam.pitch=-PI_3; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); Game::World.init ( ) .setType(NewObjs,OBJ_ITEM ) // use OBJ_ITEM type because objects in the world we're using are saved with OBJ_ITEM type .New ("world/custom params"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\10 - Dynamically Created Objects.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** In this tutorial is presented how to dynamically create objects /******************************************************************************/ Game::ObjMemx<Game::Item> Items; /******************************************************************************/ void InitPre() { App.name("Dynamically Created Objects"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); Cam.dist =16; Cam.yaw =-PI_4; Cam.pitch=-0.5; Cam.at.set(16,0,16); } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).pos.set(0,1,0); Game::World.init ( ) .setType(Items,OBJ_ITEM ) .New ("world/barrels") .update (Cam.at ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); if(Kb.bp(KB_SPACE)) // on space { Game::ObjParams &obj=*Game::Objs("obj/item/misc/barrel/0.obj"); // get barrel object parameters Game::World.objCreate(obj,Matrix(obj.scale(),Vec(16,8,16))); // create new object at (16,8,16) position and give objects default scaling } return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to add a Barrel"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\11 - Waypoints.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ void InitPre() { App.name("Waypoints"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).ambPower(0.3); ViewportFull.range=50; Cam.at.set(16,0,16); Cam.dist = 20; Cam.pitch=-PI_3; } /******************************************************************************/ Bool Init() { Text_ds.scale*=0.8; Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); Game::World.init( ) .New ("world/waypoints"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void DrawWaypoints(Str name) { if(Game::Waypoint *waypoint=Game::World.findWaypoint(name)) // if waypoint exists { waypoint->draw( ); // draw waypoint Vec pos=waypoint->pos (Tm.time()*2); // access waypoints position at 'Tm.time()*2' length pos.draw(RED); // draw the position as red dot } } void Draw() { Renderer(Render); // draw waypoints // 3 waypoints are stored in World used in this tutorial, they're named as follow: "0", "1", "2" SetMatrix(); // first reset matrix REP(3)DrawWaypoints(S+i); // draw each waypoint D.text(0,0.9,"Notice that different Waypoints have different looping modes"); D.text(0,0.8,"Waypoints with their looping modes are set in World Editor"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\12 - Character Animations.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct Player : Game::Chr { Motion attack; virtual void animate(); // extend skeleton animation virtual Bool update (); // io virtual void save(File &f); virtual Bool load(File &f); }; /******************************************************************************/ void Player::animate() { __super::animate(); // call default animations // now the skeleton is animated with default character animations (walking, running, crouching, ..) // so after the basic animations we can optionally replace them with custom ones, for example attacking: cskel.animate(attack,true); // animate skeleton with 'attack' animation motion, 'true' for replace animation mode } /******************************************************************************/ Bool Player::update() { if(action) { if(Kb.b(KB_W) || Kb.b(KB_S) || Kb.b(KB_A) || Kb.b(KB_D) || Kb.b(KB_Q) || Kb.b(KB_E))actionBreak(); } if(!action) { // turn & move input.anglei.x=Kb.b(KB_Q)-Kb.b(KB_E); input.anglei.y=Kb.b(KB_T)-Kb.b(KB_G); input.diri .x=Kb.b(KB_D)-Kb.b(KB_A); input.diri .z=Kb.b(KB_W)-Kb.b(KB_S); input.diri .y=Kb.b(KB_SPACE)-Kb.b(KB_LSHIFT); // dodge, crouch, walk, jump input.dodge = Kb.bd(KB_D)-Kb.bd(KB_A); input.crouch= Kb.b (KB_LSHIFT); input.walk = Kb.b (KB_LCTRL ); input.jump =(Kb.bp(KB_SPACE ) ? 3.5 : 0); // mouse turn Flt max=DegToRad(900)*Tm.d(), dx =Ms.dir_ds.x*1.7, dy =Ms.dir_ds.y*1.7*Ms.inv(); angle.x-=Mid(dx,-max,max); angle.y+=Mid(dy,-max,max); // ready stance change ready^=Kb.bp(KB_R); } // update animation { if(Kb.bp(KB_ENTER)) // on enter pressed attack.set(cskel,"anim/swing/r-l.anim"); // initialize "right-hand swing to left direction" attack animation attack.updateAuto(3,3,1); // update attack animation motion } return __super::update(); } /******************************************************************************/ void Player::save(File &f) { __super::save(f); attack.save(f); } Bool Player::load(File &f) { if(__super::load(f)) { return attack.load(f,cskel); } return false; } /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; Game::ObjMemx<Game::Item > Items ; Game::ObjMemx< Player> Players; /******************************************************************************/ void InitPre() { App.name("Character Animations"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); Game::World.init() .setType(Statics,OBJ_STATIC) .setItem(Items ,OBJ_ITEM ) .setType(Players,OBJ_CHR ) .New ("world/sample" ); Cam.setSpherical(Vec(16,0,16),-PI_4,-0.5,0,10).set(); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.9,"Press Enter to play a custom animation"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\13 - Character Default Animations.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct Chr : Game::Chr { Int move_to; // index of Waypoint point to move to virtual void create(Game::ObjParams &obj); // override default creation method to setup custom default animations after character creation virtual Bool update(); // override default updating to set movement commands Chr(); }; /******************************************************************************/ Game::ObjMemx<Game::Static> Statics ; Game::ObjMemx< Chr > Chrs ; Game::Waypoint *waypoint; // pointer to waypoint stored in world /******************************************************************************/ Chr::Chr() { move_to=0; } void Chr::create(Game::ObjParams &obj) { __super::create(obj); // call default creation // now when object has been created we can optionally override its default animations // for example change it's walking animation // to achieve this we need to change the default animation from characters skeleton animation cache 'Chr::sac' // on the test map used with this tutorial, there are 2 characters human and a skeleton // we'll replace the animation only for the skeleton character leaving human character with its default animation // detect if current character is a skeleton Bool is_skeleton=false; for(Game::ObjParams *cur=&obj; cur; cur=cur->base()) // iterate through all ObjParams bases if(CChar *name=Game::Objs(cur)) // if received the name of the object if(Contains(name,"skeleton")) // if the object name contains "skeleton" word { is_skeleton=true; break; } // replace the animation if(is_skeleton) // only for the skeleton { sac.walk=&cskel.getSkelAnim("anim/custom/scary walk.anim"); // this will load the animation, cache it, and set into character's animation } move_walking=true; // order the characters to always move by walking instead of running } Bool Chr::update() { if(__super::update()) { if(!action) // if not performing any action { if(waypoint && waypoint->points()) // if have waypoint with some points in it { move_to=(move_to+1)%waypoint->points(); // set variable to next point index actionMoveTo(waypoint->point(move_to).pos); // order the character to move to the point position } } return true; } return false; } /******************************************************************************/ void InitPre() { App.name("Character Default Animations"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).shdMode(SHD_NONE).ambPower(0.3); } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); // create the world Game::World.init() .setType(Statics,OBJ_STATIC) .setType(Chrs ,OBJ_CHR ) .New ("world/animations"); // access the Waypoint waypoint=Game::World.getWaypoint("0"); // load waypoint named "0" stored in current world Cam.setSpherical(Vec(17,2,12),-0.4,-0.9,0,11).set(); // set initial camera return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1) ? CAMH_MOVE : CAMH_ROT)); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\14 - Character Facial Animations.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct Player : Game::Chr { virtual void animate(); // extend skeleton animation virtual Bool update (); // optionally you can override default 'face blend' value by defining your own function virtual Flt animateFaceBlend(); }; /******************************************************************************/ void Player::animate() { __super::animate(); // call default animations // facial animation { Flt blend=animateFaceBlend(); // get facial animation blending value // this is a factor which determines the intensity of facial animations // for example if the character is near the camera the blend is full (1.0) so facial animations will be performed normally // and if the character is far away so face isn't visible very well, blending value will be disabled (0.0) // disabling facial animations speeds up rendering process, so its visible only in some distance from camera if(blend>0) { Flt time =Tm.time(), smile_blend=1; cskel.animate(L"anim/face/smile.anim",time,smile_blend*blend); } } } Flt Player::animateFaceBlend() { Flt distance =Dist(pos(),Cam.matrix.pos), // distance from camera full_blend_range=1 , // custom range where the facial animation should be full (1 meter) no_blend_range=1.5; // custom range where the facial animation should be disabled (1.5 meter) return LerpRS(no_blend_range,full_blend_range,distance); // this will returned a saturated value 0..1 } /******************************************************************************/ Bool Player::update() { if(action) { if(Kb.b(KB_W) || Kb.b(KB_S) || Kb.b(KB_A) || Kb.b(KB_D) || Kb.b(KB_Q) || Kb.b(KB_E))actionBreak(); } if(!action) { // turn & move input.anglei.x=Kb.b(KB_Q)-Kb.b(KB_E); input.anglei.y=Kb.b(KB_T)-Kb.b(KB_G); input.diri .x=Kb.b(KB_D)-Kb.b(KB_A); input.diri .z=Kb.b(KB_W)-Kb.b(KB_S); input.diri .y=Kb.b(KB_SPACE)-Kb.b(KB_LSHIFT); // dodge, crouch, walk, jump input.dodge = Kb.bd(KB_D)-Kb.bd(KB_A); input.crouch= Kb.b (KB_LSHIFT); input.walk = Kb.b (KB_LCTRL ); input.jump =(Kb.bp(KB_SPACE ) ? 3.5 : 0); // mouse turn Flt max=DegToRad(900)*Tm.d(), dx =Ms.dir_ds.x*1.7, dy =Ms.dir_ds.y*1.7*Ms.inv(); angle.x-=Mid(dx,-max,max); angle.y+=Mid(dy,-max,max); // ready stance change ready^=Kb.bp(KB_R); } return __super::update(); } /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; // container for static objects Game::ObjMemx< Player> Players; // container for player objects /******************************************************************************/ void InitPre() { App.name("Character Facial Animation"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).shdSoft(1).ambPower(0.3).hpRt(true); ViewportFull.range=20; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.rays.mode=SUN_RAYS_HIGH; // create the world Game::World.init() .setType(Statics,OBJ_STATIC) .setType(Players,OBJ_CHR ) .New ("world/sample" ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); if(Players.elms())Cam.setSpherical(Players[0].cskel.getPoint("Head").pos,Players[0].angle.x+PI,-Players[0].angle.y,0,Max(0.1f,Cam.dist*ScaleFactor(Ms.wheel*-0.2))).updateVelocities().set(); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); if(Players.elms())D.text(0,0.9,S+"Facial blending factor for Players[0] is: "+Players[0].animateFaceBlend()); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\15 - Character Ragdoll.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; // container for static objects Game::ObjMemx<Game::Chr > Chrs ; // container for player objects /******************************************************************************/ void InitPre() { App.name("Character Ragdoll"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).shdSoft(1).ambPower(0.3); ViewportFull.range=30; Cam.at.set(16,0,16); Cam.yaw =-PI_4; Cam.pitch =-0.5; Cam.dist =4; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Suns .New ().set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); // create the world Game::World.init() .setType(Statics,OBJ_STATIC) .setType(Chrs ,OBJ_CHR ) .New ("world/sample" ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); if(Chrs.elms()) { Game::Chr &chr=Chrs[0]; if(Kb.bp(KB_1))chr.ragdollEnable (); // switch to ragdoll if(Kb.bp(KB_2))chr.ragdollDisable(); // switch to skeleton animation if(Kb.bp(KB_Q))if(chr.ragdollBlend())if(Actor *actor=chr.ragdoll.findActor("Head" ))actor->addVel(Vec(0,0,3)); if(Kb.bp(KB_W))if(chr.ragdollBlend())if(Actor *actor=chr.ragdoll.findActor("Body" ))actor->addVel(Vec(0,0,3)); if(Kb.bp(KB_E))if(chr.ragdollBlend())if(Actor *actor=chr.ragdoll.findActor("FootR"))actor->addVel(Vec(0,0,4)); if(Kb.bp(KB_R))if(chr.ragdollBlend())if(Actor *actor=chr.ragdoll.findActor("HandR"))actor->addVel(Vec(0,0,4)); Cam.setSpherical(chr.pos(),Cam.yaw-Ms.d.x,Cam.pitch+Ms.d.y,0,Max(0.1f,Cam.dist*ScaleFactor(Ms.wheel*-0.2))).updateVelocities().set(); } return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.9,"Press 1,2 to switch between skeleton<->ragdoll animation"); D.text(0,0.8,"Press q,w,e,r to simulate shot hits"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\16 - Camera Modes.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** Here we'll present how to properly use different camera modes /******************************************************************************/ // Define viewing modes: enum VIEW_MODE // Viewing Mode { VIEW_FPP, // First Person VIEW_TPP, // Third Person VIEW_ISO, // Isometric VIEW_NUM, // number of view modes }; U32 View; // current VIEW_MODE /******************************************************************************/ struct Player : Game::Chr { virtual Bool update(); virtual void draw(); // extend drawing to disable head rendering in FPP mode }; /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; // container for static objects Game::ObjMemx<Game::Item > Items ; // container for item objects Game::ObjMemx< Player> Players; // container for player objects /******************************************************************************/ Bool Player::update() { if(action) { if(Kb.b(KB_W) || Kb.b(KB_S) || Kb.b(KB_A) || Kb.b(KB_D) || Kb.b(KB_Q) || Kb.b(KB_E))actionBreak(); } if(!action) { // turn & move input.anglei.x=Kb.b(KB_Q)-Kb.b(KB_E); input.anglei.y=Kb.b(KB_T)-Kb.b(KB_G); input.diri .x=Kb.b(KB_D)-Kb.b(KB_A); input.diri .z=Kb.b(KB_W)-Kb.b(KB_S); input.diri .y=Kb.b(KB_SPACE)-Kb.b(KB_LSHIFT); // dodge, crouch, walk, jump input.dodge = Kb.bd(KB_D)-Kb.bd(KB_A); input.crouch= Kb.b (KB_LSHIFT); input.walk = Kb.b (KB_LCTRL ); input.jump =(Kb.bp(KB_SPACE ) ? 3.5 : 0); // mouse turn if(View!=VIEW_ISO) // don't use mouse turning when in Isometric mode { Flt max=DegToRad(900)*Tm.d(), dx =Ms.dir_ds.x*1.7, dy =Ms.dir_ds.y*1.7*Ms.inv(); angle.x-=Mid(dx,-max,max); angle.y+=Mid(dy,-max,max); } // ready stance change ready^=Kb.bp(KB_R); } return __super::update(); } void Player::draw() { Bool disable_head_draw=(View==VIEW_FPP && Renderer()!=RM_SHD_MAP && mesh); // disable drawing head when we're in FPP mode and we're not in shadowing mode (if this isn't included player will cast head-less shadows) if(disable_head_draw)mesh->hide("head"); // hide "head" mesh part in 'mesh' __super::draw(); // call default drawing if(disable_head_draw)mesh->show("head"); // un-hide "head" mesh part, so other objects which use the same mesh will have the head rendered properly } /******************************************************************************/ void InitPre() { App.name("Camera Modes"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3).hpRt(true); } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.rays.mode=SUN_RAYS_HIGH; // create the world Game::World.init() .setType(Statics,OBJ_STATIC) .setType(Players,OBJ_CHR ) .setItem(Items ,OBJ_ITEM ) .New("world/sample" ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); // set next camera mode when Tab pressed if(Kb.bp(KB_TAB)) { View=(View+1)%VIEW_NUM; if(View==VIEW_ISO) // when set to isometric view { Cam.dist = 10; // set bigger camera distance at start Cam.pitch=-PI_4; // set starting camera pitch angle } } // setup the camera if(Players.elms()) // if we have at least one player { // set camera depending on current view mode switch(View) { case VIEW_FPP: { OrientP &head=Players[0].cskel.getPoint("head"); // obtain player "head" skeleton point (this was created in Mesh Editor) Cam.setPosDir(head.pos,head.dir,head.perp); // set camera from 'head' position, direction and perpendicular to direction }break; case VIEW_TPP: { Cam.dist=Max(1.0f,Cam.dist*ScaleFactor(Ms.wheel*-0.1)); // update camera distance according to mouse wheel Cam.setSpherical(Players[0].pos()+Vec(0,0.5,0), Players[0].angle.x, Players[0].angle.y, 0, Cam.dist); // set spherical camera looking at player position with given player angles }break; default: // VIEW_ISO { Cam.yaw -=Ms.ds.x; // update camera yaw angle according to mouse smooth delta x Cam.pitch+=Ms.ds.y; // update camera pitch angle according to mouse smooth delta y Clamp(Cam.pitch,-PI_2,0); // clamp to possible camera pitch angle Cam.dist =Max(1.0f,Cam.dist*ScaleFactor(Ms.wheel*-0.1)); // update camera distance according to mouse wheel Cam.setSpherical(Players[0].pos(), Cam.yaw, Cam.pitch, 0, Cam.dist); // set spherical camera looking at player using camera angles }break; } // after setting camera position and angles: Cam.updateVelocities().set(); // update camera velocities and activate it } else // when no player on the scene { CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // default camera handling actions } return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text (0,0.9,"Press Tab to switch camera modes"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\17 - Camera Collisions.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /****************************************************************************** Here we'll present how to detect camera collisions /******************************************************************************/ struct Player : Game::Chr { virtual Bool update(); }; /******************************************************************************/ Camera desired_camera; // create a helper desired camera /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; Game::ObjMemx<Game::Item > Items ; Game::ObjMemx< Player> Players; /******************************************************************************/ Bool Player::update() { if(action) { if(Kb.b(KB_W) || Kb.b(KB_S) || Kb.b(KB_A) || Kb.b(KB_D) || Kb.b(KB_Q) || Kb.b(KB_E))actionBreak(); } if(!action) { // turn & move input.anglei.x=Kb.b(KB_Q)-Kb.b(KB_E); input.anglei.y=Kb.b(KB_T)-Kb.b(KB_G); input.diri .x=Kb.b(KB_D)-Kb.b(KB_A); input.diri .z=Kb.b(KB_W)-Kb.b(KB_S); input.diri .y=Kb.b(KB_SPACE)-Kb.b(KB_LSHIFT); // dodge, crouch, walk, jump input.dodge = Kb.bd(KB_D)-Kb.bd(KB_A); input.crouch= Kb.b (KB_LSHIFT); input.walk = Kb.b (KB_LCTRL ); input.jump =(Kb.bp(KB_SPACE ) ? 3.5 : 0); // ready stance change ready^=Kb.bp(KB_R); } return __super::update(); } /******************************************************************************/ void InitPre() { App.name("Camera Collisions"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3).hpRt(true); } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.rays.mode=SUN_RAYS_HIGH; // create the world Game::World.init() .setType(Statics,OBJ_STATIC) .setType(Players,OBJ_CHR ) .setItem(Items ,OBJ_ITEM ) .New("world/sample" ); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; Game::World.update(Cam.at); // setup the camera if(Players.elms()) // if we have at least one player { // first setup the desired camera as in the previous tutorials desired_camera.yaw -=Ms.ds.x; // update camera yaw angle according to mouse smooth delta x desired_camera.pitch+=Ms.ds.y; // update camera pitch angle according to mouse smooth delta y Clamp(desired_camera.pitch,-PI_2,PI_4); // clamp to possible camera pitch angle desired_camera.dist=Max(1.0f,desired_camera.dist*ScaleFactor(Ms.wheel*-0.1)); // update camera distance according to mouse wheel desired_camera.at =Players[0].pos(); desired_camera.setSpherical(); // set as spherical from current values, this will set the camera's matrix (desired_camera.matrix) // now what we'll do is cast a small sized Ball from starting position to target camera destination // we'll stop the ball at first contact point, and set camera at that place // create a helper ball which will be used for collision detection Ball ball(0.1f, desired_camera.at); // we place it at starting point (where the camera is looking at) // now we'll move the ball in the direction where the camera should be Physics.move(ball, desired_camera.matrix.pos-ball.pos); // use physics move to move the ball as far as it can go without any collisions // now the ball.pos is located at either maximum movement distance or at nearest collision point // having ball's position we can now set the final camera position Cam.setPosDir(ball.pos, desired_camera.matrix.z, desired_camera.matrix.y); // we'll use desired_camera.matrix directions which were set in 'setSpherical' camera method Cam.updateVelocities().set(); // update camera velocities and activate it } else // when no player on the scene { CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); // default camera handling actions } return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.9,"Try to move the camera around"); D.text(0,0.8,"and see how it gets blocked by the terrain"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\18 - Object References.txt /******************************************************************************/ #include "stdafx.h" /****************************************************************************** In this tutorial is presented how to properly use references to world objects using 'Reference' class. Let's assume a Character wants to reference an Item So first let's think how we would do this the easy way: Add a pointer to an item? struct Chr : Game::Chr { Item *item; ... This looks ok, but what happens if 'item' points to the Item object, and then during a Game Update, the Item Object is removed/deleted. For example another player picked up the item, so item's memory address has moved to a inventory container. Or the item has become too far from the center of action, that the world had to flush the item object to a temporary file on the disk. In that scenario 'Chr::item' still points to a memory address but at which there is no original Item. This means that additional caution needs to be taken. To solve this problem we'll use object's 'id' value. Before going any further let's sum up how objects are handled in the world: -When each object is created it has its 'id' set to a random value different than zero -When each object is deleted its 'id' is set to zero -Object's 'id' values are saved and loaded in SaveGame -After removing/deleting a world object, its memory is still accessible, but: -it's not used at all ('id' value is zero) -it's used but by another object created later ('id' value is set to new object's 'id') So to properly reference an object we must store a pointer to its memory and its 'id', in case the referenced objects memory will be used by another object later with another 'id'. For this - 'Reference' class is used which stores a pointer and an 'id'. So for example let's use a World Character and a World Item. The Character will hold a reference to the item as 'desired_item'. /******************************************************************************/ #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct Chr : Game::Chr // extend default character { Reference<Game::Item> desired_item; // add a new parameter, which is a reference to an item (something like 'Item *desired_item;') // draw void draw2D() // this is a helper method for drawing text on the screen { if(desired_item.valid()) // check if the reference is valid { Vec pos=desired_item().pos(); // referenced objects can be accessed using operator(), but only after validation using 'valid' method as above D.text(0,0.8,S+"My desired item is at: ("+pos+") position"); } else // if the reference has become invalid { D.text(0,0.8,"My desired item is gone"); // display a text that the reference is now invalid } } // handle saving and loading, following methods are needed only for saving and loading the Reference void save(File &f) { __super::save(f); desired_item.save(f); // save Reference } Bool load(File &f) { if(__super::load(f)) { desired_item.load(f); // load Reference, here only the Reference 'id' is loaded, the pointer to the object is cleared because the object may not exist yet // searching for the actual object will be performed later (inside 'linkReferences') after all objects have been loaded return true; } return false; } void linkReferences() // this is called when all of the objects have been loaded { // in this method you should call 'link' on all references which the object contains desired_item.link(); // by calling 'link' the world manager will try to find the referenced object according to the 'id', and store its pointer into the Reference } }; /******************************************************************************/ Game::ObjMemx<Game::Static> Statics; Game::ObjMemx<Game::Item > Items ; Game::ObjMemx< Chr > Chrs ; /******************************************************************************/ void InitPre() { App.name("Object References"); App.flag=APP_MS_EXCLUSIVE|APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024); Cam.dist =10; Cam.yaw =-PI_4; Cam.pitch=-0.5; Cam.at.set(16,0,16); } /******************************************************************************/ Bool Init() { Physics.create(); Game::World.init() .setType(Statics,OBJ_STATIC) .setItem(Items ,OBJ_ITEM ) .setType(Chrs ,OBJ_CHR ) .New ("world/sample" ); // after loading the world, let's set the 'desired_item' for the Character { Game::World.update(Cam.at); // first world needs to be updated to a location to make sure that objects at that location are loaded if(Chrs.elms() && Items.elms()) // now check if the world has at least one character and one item Chrs[0].desired_item=Items[0]; // set the Character's reference to point to the first Item (this stores the item's memory address and its 'id') } return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); if(Kb.bp(KB_F2))Game::World.save("LocalData/save.sav"); // save game if(Kb.bp(KB_F3))Game::World.load("LocalData/save.sav"); // load game Game::World.update(Cam.at); if(Kb.bp(KB_SPACE) && Items.elms()) // when space pressed and if World Items has elements Items.removeValid(0); // remove 0-th item return true; } /******************************************************************************/ void Render() { Game::World.draw(); switch(Renderer()) { case RM_LIGHT: LightDir(!Vec(1,-1,1)).add(); break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to remove the item"); if(Chrs.elms())Chrs[0].draw2D(); // draw characters text } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\19 - Small Overlays.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct Marker2 : Marker // create a helper class which bases on Marker and uses time fading { Flt time; // time left until overlay fades out Marker2() { time=10; // default time is 10 seconds for an overlay to live } Bool update() { time-=Tm.d(); // decrease time left return time<=0 ; // if there is no time left then return true (which means that the overlay can be deleted) } void draw(Matrix &matrix) { Marker::draw(matrix,Sat(time)); // draw the overlay with transparency of 'Saturate(time)' value } // io void save(File &f) { Marker::save(f); f<<time; } Bool load(File &f) { if(Marker::load(f)) { f>>time; return true; } return false; } }; /******************************************************************************/ struct Item : Game::Item // extend items { Memb<Marker2> marker; // add marker, which is used for rendering semi transparent images on solid surfaces virtual Bool update(); // extend updating to include 'marker' update virtual void draw (); // extend drawing to include rendering of 'marker' // io virtual void save(File &f); // extend saving to include members saving virtual Bool load(File &f); // extend loading to include members loading // operations void addBulletHole(Vec &pos,Vec &surface_normal,Vec &shot_dir); // helper method for adding a bullet hole (Marker) onto the item mesh }; /******************************************************************************/ Game::ObjMemx<Item> Items; /******************************************************************************/ // ITEM /******************************************************************************/ Bool Item::update() { if(__super::update()) { REPA(marker)if(marker[i].update()) // update all overlays marker.remove(i,true); // and remove them if they faded out return true; } return false; } /******************************************************************************/ void Item::draw() { __super::draw(); // call default drawing switch(Renderer()) { case RM_OVERLAY: // overlays need to be rendered in RM_OVERLAY mode REPAO(marker).draw(matrixScaled()); // draw mesh_overlays with the same matrix used for default item drawing break; } } /******************************************************************************/ void Item::save(File &f) { __super::save(f); marker.save(f); } Bool Item::load(File &f) { if(__super::load(f)) { return marker.load(f); } return false; } /******************************************************************************/ void Item::addBulletHole(Vec &pos,Vec &surface_normal,Vec &shot_dir) { // add a marker to the item marker.New().set(WHITE,0,*Gfxs("gfx/hole/bullet.gfx"),0.1f,0.05f,0.05f).matrix(matrixScaled(),Matrix().setPosDir(pos,surface_normal)); // add impulse to the actor actor.addImpulse(shot_dir * 1.5f,pos); } /******************************************************************************/ // MAIN /******************************************************************************/ void InitPre() { App.name("Small Overlays"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=70; Cam.at.set(16,2,12); Cam.dist = 0.01; Cam.pitch=-0.2f; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.rays.mode=SUN_RAYS_HIGH; Game::World.init ( ) .setItem(Items,OBJ_ITEM ) .New ("world/custom params"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; // update the camera FPP 'WSAD' style if(Kb.b(KB_A ))Cam.at-=Cam.matrix.x*Tm.d()*2; if(Kb.b(KB_D ))Cam.at+=Cam.matrix.x*Tm.d()*2; if(Kb.b(KB_S ))Cam.at-=Cam.matrix.z*Tm.d()*2; if(Kb.b(KB_W ))Cam.at+=Cam.matrix.z*Tm.d()*2; if(Kb.b(KB_LSHIFT))Cam.at-=Vec(0,1,0) *Tm.d()*2; if(Kb.b(KB_SPACE ))Cam.at+=Vec(0,1,0) *Tm.d()*2; CamHandle(0.01,0.01,CAMH_ROT); // allow only rotation Game::World.update(Cam.at); if(Ms.bp(0)) // on LMB pressed { // calculate world position and direction vectors Vec pos, dir; ScreenToPosDir(Vec2(0,0),pos,dir); PhysHit phys_hit; if(Physics.ray(pos,dir*Viewport.range,&phys_hit)) // if ray test hit an actor { if(phys_hit.obj) // if the actor comes from an object { if(Item *item=CAST(Item,phys_hit.obj)) // if the object is an item { item->addBulletHole(phys_hit.plane.p, phys_hit.plane.n, dir); // call item method to add a bullet hole } } else // the actor doesn't have an object set, so most probably it's a terrain actor { // add a marker to the world terrain Game::World.terrainAddMarker(WHITE,0,*Gfxs("gfx/hole/bullet.gfx"),Matrix().setPosDir(phys_hit.plane.p, phys_hit.plane.n),0.1f,0.05f,0.05f); } } } return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); D.text(0,0.9,"Press LMB to shoot"); // draw simple crosshair D.lineX(WHITE, 0, -0.08f,0.08f); D.lineY(WHITE, 0, -0.08f,0.08f); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\4 - Demos, Game Basics\Game Basics\20 - Big Overlays.txt /******************************************************************************/ #include "stdafx.h" #include "../../../../../data/enum/_enums.h" /******************************************************************************/ struct MeshOverlay2 : MeshOverlay // create a helper class which bases on MeshOverlay and uses time fading { Flt time; // time left until overlay fades out MeshOverlay2() { time=10; // default time is 10 seconds for an overlay to live } Bool update() { time-=Tm.d(); // decrease time left return time<=0 ; // if there is no time left then return true (which means that the overlay can be deleted) } void draw(Matrix &matrix) { MeshOverlay::draw(matrix,Sat(time)); // draw the overlay with transparency of 'Saturate(time)' value } // io void save(File &f) { MeshOverlay::save(f); f<<time; } Bool load(File &f) { if(MeshOverlay::load(f)) { f>>time; return true; } return false; } }; /******************************************************************************/ struct Item : Game::Item // extend items { I32 type ; // ITEM_TYPE Memb<MeshOverlay2> mesh_overlay; // add mesh overlay, which is used for rendering semi transparent images on solid surfaces virtual void create(Game::ObjParams &obj); // extend creation to include accessing item type virtual Bool update( ); // extend updating to include bomb explosion, and 'mesh_overlay' update virtual void draw ( ); // extend drawing to include rendering of 'mesh_overlay' // io virtual void save(File &f); // extend saving to include members saving virtual Bool load(File &f); // extend loading to include members loading Item(); }; /******************************************************************************/ Memb<ExplosionFx> explosion; Game::ObjMemx<Item> Items; /******************************************************************************/ void CreateExplosion(Vec &pos) // helper function for creating an explosion at given position { // add an earthquake effect QuakeFx.addMedium(); // create a new explosion effect explosion.New().create(Gfxs("gfx/particle/explosion/0.gfx"),Gfxs("gfx/particle/explosion/1.gfx"),0x00600000,32,pos,3); // set overlay parameters Flt overlay_angle=RandomF(PI2), overlay_scale=RandomF(4,7); Gfx &overlay_gfx =*Gfxs("gfx/hole/bomb.gfx"); // add terrain overlay Matrix m; m.setPosDir (pos,Vec(0,-1,0)); // set position and direction m.orn.rotateZVec(overlay_angle ); // rotate along matrix z axis m.scaleOrn (overlay_scale ); // scale the overlay Game::World.terrainAddOverlay(WHITE,0,overlay_gfx,m); Memb<Game::Obj*> objects; Game::World.objQuery(objects,Ball(overlay_scale*SQRT3+1,pos),OBJ_ITEM); // get objects in explosion radius REPA(objects)if(Item *item=CAST(Item,objects[i])) // process world items to add overlays and apply forces to actors { // apply forces to item actors Actor &actor=item->actor; Vec dir =actor.pos()-pos; // get difference between actor position and explosion position Flt dist =dir.normalize(); // normalize direction and store its previous length into 'dist' dist*=dist; // distance is now equal to squared distance if(dist)actor.addImpulse(30 * dir / dist); // final equation for impulse = (power) * (normalized direction) / (distance^2) // set mesh overlay for item if(item->mesh) { m.orn.setDir (dir); m.orn.rotateZVec(overlay_angle); m.scaleOrn (overlay_scale); if(!item->mesh_overlay.New().create(*item->mesh,overlay_gfx,m,&item->matrixScaled()))item->mesh_overlay.removeLast(); } } } /******************************************************************************/ // ITEM /******************************************************************************/ Item::Item() { type=ITEM_NONE; } /******************************************************************************/ void Item::create(Game::ObjParams &obj) { __super::create(obj); if(Game::Param *param=obj.findParam("type"))type=param->asEnum(); // get item type from .obj file } /******************************************************************************/ Bool Item::update() { if(__super::update()) { if(type==ITEM_MISSILE) // if this is a missile { Vec vec=actor.vel(); vec*=Tm.d()*3; if(actor.sweep(vec)) // if the missile actor has encountered an obstacle along the way { CreateExplosion(pos()); // create explosion at bomb's position return false; // return false which will delete the bomb Item } } REPA(mesh_overlay)if(mesh_overlay[i].update()) // update all overlays mesh_overlay.remove(i,true); // and remove them if they faded out return true; } return false; } /******************************************************************************/ void Item::draw() { __super::draw(); // call default drawing switch(Renderer()) { case RM_OVERLAY: // mesh overlays need to be rendered in RM_OVERLAY mode REPAO(mesh_overlay).draw(matrixScaled()); // draw mesh_overlays with the same matrix used for default item drawing break; } } /******************************************************************************/ void Item::save(File &f) { __super::save(f); f<<type; mesh_overlay.save(f); } Bool Item::load(File &f) { if(__super::load(f)) { f>>type; return mesh_overlay.load(f); } return false; } /******************************************************************************/ // MAIN /******************************************************************************/ void InitPre() { App.name("Big Overlays"); App.flag=APP_FULL_TOGGLE|APP_MS_EXCLUSIVE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=70; Cam.at.set(16,0,16); Cam.dist = 28; Cam.pitch=-PI_6; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.rays.mode=SUN_RAYS_HIGH; // increase default earthquake effect scale QuakeFx.scale*=3; Game::World.init ( ) .setItem(Items,OBJ_ITEM ) .New ("world/custom params"); return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_MOVE:CAMH_ROT)); Game::World.update(Cam.at); // update earthquake effect QuakeFx.update(); // update explosions REPA(explosion)if(explosion[i].update())explosion.remove(i); if(Kb.bp(KB_SPACE)) // on space pressed { // create a 'bomb' item Game::ObjParams &bomb=*Game::Objs("obj/item/missile/bomb/0.obj"); Game::World.objCreate(bomb,Matrix().setPosUp(Vec(RandomF(13,19),14,RandomF(13,19)),Vec(0,-1,0)).scaleOrn(bomb.scale()*2)); } return true; } /******************************************************************************/ void Render() { Game::World.draw(); switch(Renderer()) { case RM_PALETTE: REPA(explosion)explosion[i].draw(); // draw explosions break; } } void Draw() { Renderer(Render); D.text(0,0.9,"Press Space to drop a Bomb"); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\01 - Simple Project\Game.txt /******************************************************************************/ #include "stdafx.h" #include "Main.h" /******************************************************************************/ Bool InitGame() { return true; } void ShutGame() { } /******************************************************************************/ Bool UpdateGame() { if(Kb.bp(KB_ESC))StateMenu.set(1.0); return true; } void DrawGame() { D.clear(TURQ); D.text (0,0,"Game"); } /******************************************************************************/ State StateGame(UpdateGame,DrawGame,InitGame,ShutGame); /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\01 - Simple Project\Intro.txt /******************************************************************************/ #include "stdafx.h" #include "Main.h" /******************************************************************************/ Bool InitIntro() { return true; } void ShutIntro() { } /******************************************************************************/ Bool UpdateIntro() { if(StateActive->time()>3 || Kb.bp(KB_ESC)) StateMenu.set(1.0); return true; } void DrawIntro() { D.clear(BLACK); D.text (0,0,"Intro"); } /******************************************************************************/ State StateIntro(UpdateIntro,DrawIntro,InitIntro,ShutIntro); /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\01 - Simple Project\Main.txt /******************************************************************************/ #include "stdafx.h" #include "Main.h" // include the main header, which includes all other headers /******************************************************************************/ void InitPre() { App.name("Simple Multi CPP Project"); IOPath("../data"); PakAdd("engine.pak"); } Bool Init() { StateIntro.set(); return true; } void Shut() { } /******************************************************************************/ Bool Main() { return true; } void Draw() { } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\01 - Simple Project\Menu.txt /******************************************************************************/ #include "stdafx.h" #include "Main.h" /******************************************************************************/ Bool InitMenu() { return true; } void ShutMenu() { } /******************************************************************************/ Bool UpdateMenu() { if(Kb.bp(KB_ESC))return false; if(Kb.bp(KB_ENTER))StateGame.set(0.5); return true; } void DrawMenu() { D.clear(GREY); D.text (0, 0 ,"Menu"); D.text (0,-0.3,"Press Enter to start the game"); D.text (0,-0.5,"Press Escape to exit"); } /******************************************************************************/ State StateMenu(UpdateMenu,DrawMenu,InitMenu,ShutMenu); /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\02 - Inventory\Inventory Gui.txt /******************************************************************************/ #include "stdafx.h" #include "main.h" /******************************************************************************/ InventoryGui InvGui; /******************************************************************************/ // MANAGE /******************************************************************************/ void InventoryGui::create() { // window Gui+=window.create(Rect_R(D.w(),0,1,1.5f),"Inventory"); // slots { // background images Flt w=0.11, // default unit width s=0.03; // default unit spacing Gfx *gfx=Gfxs("gfx/inventory/slot.gfx"); window+=slot_img[SLOT_HEAD ][0].create(Rect_U (window.crect.w()/2 , -0.05, w*2,w*2),gfx).desc("Head"); window+=slot_img[SLOT_BODY ][0].create(Rect_U (window.crect.w()/2 , slot_img[SLOT_HEAD][0].rect.min.y-s, w*2,w*3),gfx).desc("Body"); window+=slot_img[SLOT_ARM_L][0].create(Rect_RU(slot_img[SLOT_BODY][0].rect.min.x-s, slot_img[SLOT_BODY][0].rect.max.y , w*2,w*3),gfx).desc("Left Arm"); window+=slot_img[SLOT_ARM_R][0].create(Rect_LU(slot_img[SLOT_BODY][0].rect.max.x+s, slot_img[SLOT_BODY][0].rect.max.y , w*2,w*3),gfx).desc("Right Arm"); // item images REPA(slot_img)if(i!=SLOT_TEMP) { window+=slot_img[i][1].create(slot_img[i][0].rect).desc(slot_img[i][0].desc()); slot_img[i][1].rect_color=0; } } // region { Rect_LU rect(0,0,window.crect.w(),window.crect.h()); rect.max.y=rect.min.y+0.7f; rect.extend(-0.05f); window+=region.create(rect); } // list { ListGroup lg[]= { ListGroup(MEMBER(Item,icon ),0.2f,L"Icon" ), // 0 ListGroup(MEMBER(Item,name ),0.5f,L"Name" ), // 1 ListGroup(MEMBER(Item,power),0.2f,L"Power"), // 2 }; lg[2].precision=1; // set showing only 1 decimal precision for power float attribute region+=list.create(lg,ELMS(lg)); list. cur_mode=LCM_MOUSE; list.draw_mode=LDM_RECTS; } } /******************************************************************************/ // OPERATIONS /******************************************************************************/ void InventoryGui::link(Inventory *inv) { if(T.inv!=inv) { T.inv=inv; if(inv)inv->inv_gui=this; setGui(); } } /******************************************************************************/ void InventoryGui::setGui() { if(inv) { // set item list { // here we have to hide the items which are assigned to slots // create a 'is' array which determines visibility of an element (1=visible, 0=hidden) Byte *is=AllocN(Byte,inv->items.elms()); // allocate bytes for all items in container SetMem(is,1,inv->items.elms()); // set memory to '1' (make all items visible by default) REPA(inv->slot) // iterate through all slots { if(inv->slot[i].valid()) // if the slot is valid { Int index=inv->items.validIndex(&inv->slot[i]()); // get index of a slot item in items container if(InRange(index,inv->items)) // if its valid is[index]=0; // set visibility for item assigned to a slot to 0, to be hidden on the list } } list.setData(inv->items,is); // set list data from items container and visibility list Free(is); // free allocated memory } // set slot images REP(SLOT_NUM) // for all slots if(i!=SLOT_TEMP) // skip temporary slot because it's not drawn using 'Image' class { Image &img_back= slot_img[i][0], // background image, we use it for accessing its rectangle &img_item= slot_img[i][1]; // item image Reference<Item> & item=inv->slot [i] ; // item at slot if(!item.valid())img_item.set(NULL);else // if there is no item then clear the item image slot { Gfx *icon=item().icon; // access item's icon img_item.set(icon); // set slot image as the item's icon if(icon) // set proper scaling { Vec2 size(icon->x(),icon->y()); size*=PIXEL_SIZE; // set default size if(size.x>img_back.rect.w())size*=img_back.rect.w()/size.x; // clamp item size to background slot width if(size.y>img_back.rect.h())size*=img_back.rect.h()/size.y; // clamp item size to background slot height Rect rect(img_back.rect.center()); rect.extend(size/2); img_item.setRect(rect); } } } }else { list.clear(); REP(SLOT_NUM)slot_img[i][1].set(NULL); } } /******************************************************************************/ // UPDATE /******************************************************************************/ void InventoryGui::update(Game::Chr &owner) { if(inv) { if(Ms.bp(0)) // if mouse button pressed { if(inv->slot[SLOT_TEMP].valid()) // if we have an item attached with mouse { if(Gui.ms==&list) // if mouse cursor is on the list { inv->slot[SLOT_TEMP].clear(); // clear the slot reference which will result in "putting back the item into the list" setGui(); // update visuals }else if(Gui.ms==Gui.desktop || !Gui.ms) // if mouse cursor is on the desktop or nothing (this means the game world area) { owner.itemDropDown(inv->slot[SLOT_TEMP]()); // drop the item onto the world } } else // we don't have an item so we want to get one { if(Gui.ms==&list) // from the list { if(Item *item=list()) { inv->slot[SLOT_TEMP]=item; setGui(); } } } REP(SLOT_NUM) if(Gui.ms==&slot_img[i][0] || Gui.ms==&slot_img[i][1]) // if we want to put the item onto the i-th slot if(inv->slotsCanBeSwapped(SLOT_TEMP,i)) { Swap(inv->slot[SLOT_TEMP],inv->slot[i]); // swap temporary with i-th slot setGui(); // update visuals } } } } /******************************************************************************/ // DRAW /******************************************************************************/ void InventoryGui::draw() { if(inv && inv->slot[SLOT_TEMP].valid())inv->slot[SLOT_TEMP]().drawIcon(Ms.pos); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\02 - Inventory\Inventory.txt /******************************************************************************/ #include "stdafx.h" #include "main.h" /******************************************************************************/ Inventory::~Inventory() { if(inv_gui)inv_gui->unlink(); } /******************************************************************************/ // GET /******************************************************************************/ Bool Inventory::slotCanBePutTo(Int src,Int dest) { if(!InRange(src,SLOT_NUM) || !InRange(dest,SLOT_NUM))return false; if(slot[src].valid())switch(dest) { case SLOT_HEAD: case SLOT_BODY: if(slot[src]().type==ITEM_WEAPON)return false; break; } return true; } Bool Inventory::slotsCanBeSwapped(Int a,Int b) { return slotCanBePutTo(a,b) && slotCanBePutTo(b,a); } /******************************************************************************/ // OPERATIONS /******************************************************************************/ void Inventory::itemRemoved(Game::Item &item) // when an item is being removed from a character { // perform check if it is a equipped item REPA(slot) // for all slots if(slot[i]==item) // if i-th slot is set to item which is being removed slot[i].clear(); // clear the slot so it can no longer be referenced to the removed item } void Inventory::itemRemoved( ){setGui();} // when item has been removed from a character void Inventory::itemAdded (Game::Item &item){setGui();} // when item has been added to a character void Inventory::setGui ( ){if(inv_gui)inv_gui->setGui();} /******************************************************************************/ // UPDATE /******************************************************************************/ void Inventory::update(Game::Chr &owner) { if(inv_gui)inv_gui->update(owner); // set matrixes for items in hands if(slot[SLOT_ARM_L].valid()) if(OrientP *point=owner.cskel.findPoint("HandL")) slot[SLOT_ARM_L]().matrix(Matrix().setPosDir(point->pos,point->perp,point->dir)); if(slot[SLOT_ARM_R].valid()) if(OrientP *point=owner.cskel.findPoint("HandR")) slot[SLOT_ARM_R]().matrix(Matrix().setPosDir(point->pos,point->perp,point->dir)); } /******************************************************************************/ // DRAW /******************************************************************************/ void Inventory::draw(Game::Chr &owner) { // draw items in hands if(slot[SLOT_ARM_L].valid())slot[SLOT_ARM_L]().draw(); if(slot[SLOT_ARM_R].valid())slot[SLOT_ARM_R]().draw(); } /******************************************************************************/ // IO /******************************************************************************/ void Inventory::save(File &f) { FREPA(slot) // for all slots f.putI32(items.validIndex(&slot[i]())); // store the valid index of i-th slot item in 'items' container } Bool Inventory::load(File &f) { FREPA(slot) // for all slots { Int item_index=f.getI32(); // read index of i-th slot in 'items' container if(InRange(item_index,items)) // if the index is in valid range slot[i]=items[item_index]; // set the slot to point to requested item else slot[i].clear(); // clear the item reference in i-th slot } setGui(); return true; } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\02 - Inventory\Item.txt /******************************************************************************/ #include "stdafx.h" #include "main.h" /******************************************************************************/ Item::Item() { name[0]=0; type=ITEM_NONE; power=0; icon=NULL; } /******************************************************************************/ // MANAGE /******************************************************************************/ void Item::create(Game::ObjParams &obj) { __super::create(obj); // set name if(Game::Param *p=obj.findParam("name"))Set(name,p->asStr()); // set type if(Game::Param *p=obj.findParam("type"))type=p->asEnum(); // set power if(Game::Param *p=obj.findParam("power"))power=p->asFlt(); // get icon for(Game::ObjParams *op=&obj; op; op=op->base()) // iterate through all ObjParams, to find first with a valid icon if(CChar *op_file_name=Game::Objs(op)) // if current ObjParams is stored in a file (the file name is not NULL) if(icon=Gfxs.get(GetExtNot(op_file_name)+".ico.gfx")) // if there exists an icon with the same name as ObjParams but with different extension break; // break } /******************************************************************************/ // DRAW /******************************************************************************/ void Item::draw() { if(Lit==this && Renderer()==RM_SOLID)SetHighlight(0x303030); __super::draw(); if(Lit==this && Renderer()==RM_SOLID)SetHighlight(0); } /******************************************************************************/ void Item::drawIcon(Vec2 &pos) { if(icon) { icon->drawFit(pos.x,pos.y, icon->x()*PIXEL_SIZE, icon->y()*PIXEL_SIZE); } } /******************************************************************************/ // IO /******************************************************************************/ void Item::save(File &f) { __super::save(f); f<<name<<power<<type; f.putStr16(Gfxs(icon)); } Bool Item::load(File &f) { if(__super::load(f)) { f>>name>>power>>type; icon=Gfxs(f.getStr16()); return true; } return false; } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\02 - Inventory\Main.txt /******************************************************************************/ #include "stdafx.h" #include "main.h" /******************************************************************************/ Game::Obj *Lit ; // highlighted world object Game::ObjMemx<Item > Items ; Game::ObjMemx<Player> Players; /******************************************************************************/ void InitPre() { App.name("Inventory"); App.flag=APP_FULL_TOGGLE; IOPath("../data"); PakAdd("engine.pak"); D.full(true).sync(true).shdMapSize(1024).ambPower(0.3); ViewportFull.range=70; Cam.at.set(16,0,16); Cam.dist = 10; Cam.pitch=-PI_6; } /******************************************************************************/ Bool Init() { Physics.create(); Sky .set (); Sun &sun=Suns.New(); sun.set(*Gfxs("gfx/sky/sun.gfx")).light_color=1-D.ambColor(); sun.rays.mode=SUN_RAYS_HIGH; Game::World.init ( ) .setType(Players,OBJ_CHR ) .setItem(Items ,OBJ_ITEM) .New ("world/sample" ); InvGui.create(); // modify default gui visuals Gui.style_window.blur_color=0xFF442200; Gui.style_window.back_color=0xFFFF4400; Gui.style_region.back_color=0x66000000; Gui.kb_lit=0; return true; } /******************************************************************************/ void Shut() { } /******************************************************************************/ void GetWorldObjectUnderCursor() { Lit=NULL; if(!Gui.ms || Gui.ms==Gui.desktop) { Vec pos,dir; ScreenToPosDir(Ms.pos,pos,dir); PhysHit phys_hit; if(Physics.ray(pos,dir*Viewport.range,&phys_hit,1))Lit=phys_hit.obj; } } /******************************************************************************/ Bool Main() { if(Kb.bp(KB_ESC))return false; if(Players.elms())Cam.at=Players[0].pos(); CamHandle(0.1,100,CAMH_ZOOM|(Ms.b(1)?CAMH_ROT:0)); if(Kb.bp(KB_F2))Game::World.save("LocalData/save.sav"); if(Kb.bp(KB_F3))Game::World.load("LocalData/save.sav"); Game::World.update(Cam.at); Gui.update(); GetWorldObjectUnderCursor(); return true; } /******************************************************************************/ void Render() { Game::World.draw(); } void Draw() { Renderer(Render); Gui .draw(); InvGui.draw(); } /******************************************************************************/ ESENTHEL ENGINE SDK Advanced\5 - Projects (here all files from a single directory need to be included in project)\02 - Inventory\Player.txt /******************************************************************************/ #include "stdafx.h" #include "main.h" /******************************************************************************/ Player::Player() { InvGui.link(&inv); // when creating a player automatically link him with InvGui } /******************************************************************************/ // UPDATE /******************************************************************************/ Bool Player::update() { if(__super::update()) { // detect if the player wants to pickup an item if(Lit && Ms.bp(0)) // if hase highlighted object and mouse button pressed if(Item *item=CAST(Item,Lit)) // if the object is an item itemPickUp(*item); // pick it up // update the inventory inv.update(T); return true; } return false; } /******************************************************************************/ // DRAW /******************************************************************************/ void Player::draw() { __super::draw( ); inv.draw(T); } /******************************************************************************/ // IO /******************************************************************************/ void Player::save(File &f) { __super::save(f); inv.save(f); } Bool Player::load(File &f) { if(__super::load(f)) { return inv.load(f); } return false; } /******************************************************************************/