Advertisement
Shaun_B

The beginnings of a game engine

Dec 21st, 2011
552
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 14.36 KB | None | 0 0
  1. // Example of using a simple model file, including a texture
  2. //
  3. // Additional code by Shaun Bebbington to make the beginnings
  4. // of a simple game engine v0.0000000001 MMXI Donkeysoft
  5. #include <stdlib.h>
  6. #include <malloc.h>
  7. #include <psptypes.h>
  8. #include <kernel.h>
  9. #include <displaysvc.h>
  10. #include <ctrlsvc.h>
  11. #include <libgu.h>
  12. #include <libgum.h>
  13. #include <gmo/gmo_model.h>
  14. // This tells the thingy to do the animation on the Dog
  15. #define DO_ANIMATION
  16. SCE_MODULE_INFO (Model, 0, 1, 1);
  17. int sce_newlib_heap_kb_size=4096;
  18. // File names of loaded objects:
  19. #define DOG_FILE    "dog.gmo"
  20. #define CASTLE      "Castle.gmo"
  21. // Exact value of PI:
  22. #define PI 3.1415
  23. //----------------------------------------------------------------
  24. // Forward declaration
  25. //----------------------------------------------------------------
  26. static void beginScene (void);
  27. static void swapBuffers (void);
  28. static void drawDog (float x, float y, float z);
  29. static bool loadDogModel (int argc, char **argv);
  30. static void unloadDogModel ();
  31. static void drawCastle(float x, float y, float z);
  32. static bool loadCastleModel (int argc, char **argv);
  33. static void unloadCastleModel (void);
  34. static bool loadFile (const char *filename, int **buf, int *size);
  35. static void readPad (void);
  36. static void dogJump (void);
  37. //----------------------------------------------------------------
  38. // Global variables
  39. //----------------------------------------------------------------
  40. // This integer is used to control the frame-rate, when you press 'select'
  41. // the frame-rate should be toggled between 30 FPS and 60 FPS
  42. int framerate=2;
  43. // This is set true when the movement buttons are pressed as follows:
  44. // left - rotate Dog left
  45. // right - rotate Dog right
  46. // up - Zoom into castle and animate Dog
  47. // down - Zoom out of castle and animate Dog
  48. bool CTRL=false;
  49. // We're hoping to make the Dog jump, like all good platform games,
  50. // so we need a boolean to say whether jump has been activated or not:
  51. bool JUMP=false;
  52. float jump=0.5;
  53. // Variables for dog and castle - TO DO: think of a use for them!
  54. float dogx=0.00f, dogy=0.00f, dogz=0.00f;
  55. float casx=0.00f, casy=0.00f, casz=0.00f;
  56. // These variables are used to move the camera view:
  57. float camx=0, camy=1, camz=50.00f;
  58. float xdirection=0.5, ydirection=0.5, zoomdirection=0.5;
  59. static void *malloc16 (size_t size)
  60. {
  61.     return memalign (16,size);
  62. }
  63. static void free16 (void *addr)
  64. {
  65.     free (addr);
  66. }
  67. static void *malloc64 (size_t size)
  68. {
  69.     return memalign (64, (size+63)/64*64);
  70. }
  71. static void free64 (void *addr)
  72. {
  73.     free (addr);
  74. }
  75. #define PACKET_BUFSIZE (1048576)
  76. static char g_packet_buf [PACKET_BUFSIZE] __attribute__((aligned(64)));
  77. static ScePspFMatrix4 g_matrix_buf [16];
  78. static bool running=true;
  79. static SceGmoModel *model1=0;
  80. static SceGmoModel *model2=0;
  81. static ScePspFVector3 translateDog;
  82. static ScePspFVector3 rotationDog;
  83. static ScePspFVector3 scaleDog;
  84. static ScePspFVector3 translateCas;
  85. static ScePspFVector3 rotationCas;
  86. static ScePspFVector3 scaleCas;
  87. // Main class:
  88. int main (int argc, char **argv)
  89. {
  90.     // Tell kernal to use vector floating point unit for improved performance
  91.     sceKernelChangeCurrentThreadAttr (0, SCE_KERNEL_TH_USE_VFPU);  
  92.     sceCtrlSetSamplingMode (SCE_CTRL_MODE_DIGITALANALOG);
  93.     sceGuInit ();
  94.     sceGuStart (SCEGU_IMMEDIATE, g_packet_buf, PACKET_BUFSIZE);
  95.     sceGuDrawBuffer (SCEGU_PF5551, SCEGU_VRAM_BP_0, SCEGU_VRAM_WIDTH);
  96.     sceGuDispBuffer (SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT, SCEGU_VRAM_BP_1, SCEGU_VRAM_WIDTH);
  97.     sceGuDepthBuffer (SCEGU_VRAM_BP_2, SCEGU_VRAM_WIDTH);
  98.     sceGuOffset (SCEGU_SCR_OFFSETX, SCEGU_SCR_OFFSETY);
  99.     sceGuFinish ();
  100.     sceGuSync (SCEGU_SYNC_FINISH, SCEGU_SYNC_WAIT);
  101.     sceGumSetMatrixStack (g_matrix_buf, 4, 4, 8, 0);
  102.     //  Initialise heap management functions
  103.     sceGimPictureSetMemoryManager (malloc16, free16);  
  104.     sceGimPictureSetMemoryManager2 (malloc64, free64);
  105.     sceGmoModelSetMemoryManager (malloc16, free16);
  106.     sceGmoModelSetMemoryManager2 (malloc64, free64);   
  107.     if ((!loadDogModel(argc, argv)) || (!loadCastleModel(argc, argv)))
  108.     {
  109.         running=false;
  110.     }
  111.     sceGuDisplay (SCEGU_DISPLAY_ON);
  112.     while (running)
  113.     {
  114.         readPad ();
  115.         sceGuStart(SCEGU_IMMEDIATE, g_packet_buf, PACKET_BUFSIZE) ;
  116.         beginScene ();
  117.         drawDog (dogx, dogy, dogz);
  118.         drawCastle (casx, casy, casz);
  119.         sceGuFinish ();
  120.         swapBuffers ();
  121.     }
  122.     unloadDogModel ();
  123.     unloadCastleModel ();
  124.     sceGuTerm ();
  125.     return 0;
  126. }
  127. //----------------------------------------------------------------
  128. //  begin and end
  129. //----------------------------------------------------------------
  130. void beginScene (void)
  131. {
  132.     sceGuViewport (2048, 2048, SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT);
  133.     sceGuDepthRange (0xe000, 0x1000);
  134.     sceGuEnable (SCEGU_SCISSOR_TEST);
  135.     sceGuScissor (0, 0, SCEGU_SCR_WIDTH, SCEGU_SCR_HEIGHT);
  136.     sceGuClearColor (0xff800000);
  137.     sceGuClearDepth (0);
  138.     sceGuClearStencil (0);
  139.     sceGuClear (SCEGU_CLEAR_ALL);
  140.     //  Setup perspective and view transforms
  141.     sceGumMatrixMode (SCEGU_MATRIX_VIEW);
  142.     sceGumLoadIdentity ();
  143.     // Uses global variables to position the camera, can be moved on the X, Y and Z plane:
  144.     sceGumLookAt (&(ScePspFVector3){0, 0, camz}, &(ScePspFVector3){camx, camy, 0}, &(ScePspFVector3){0, 1, 0});
  145.     sceGumMatrixMode (SCEGU_MATRIX_PROJECTION);
  146.     sceGumLoadIdentity ();
  147.     sceGumPerspective (30.0f*PI/180.0f, SCEGU_SCR_ASPECT, 10.0f, 1000000.0f);
  148.     sceGumMatrixMode (SCEGU_MATRIX_WORLD);
  149.     //  Lighting
  150.     sceGuEnable (SCEGU_FOG);
  151.     sceGuFog (40, 100, 0xff800000);
  152.     sceGuEnable (SCEGU_LIGHTING);
  153.     sceGuAmbient (0xff404040);
  154.     sceGuEnable (SCEGU_LIGHT0);
  155.     sceGuLight (0, SCEGU_LIGHT_DIRECTION, SCEGU_DIFFUSE_AND_SPECULAR, &(ScePspFVector3){-5, 10, 5});
  156.     sceGuLightColor (0, SCEGU_DIFFUSE, 0xf0f0f0ff);
  157.     sceGuLightColor (0, SCEGU_SPECULAR, 0xf0f0f0ff);
  158.     sceGuLight (2, SCEGU_LIGHT_DIRECTION, SCEGU_DIFFUSE, &(ScePspFVector3){1, 0, 0});
  159.     sceGuLight (3, SCEGU_LIGHT_DIRECTION, SCEGU_DIFFUSE, &(ScePspFVector3){0, 1, 0});
  160.     sceGuColorMaterial (SCEGU_DIFFUSE | SCEGU_AMBIENT);
  161.     //  Initialise render state
  162.     sceGuEnable (SCEGU_ALPHA_TEST);
  163.     sceGuEnable (SCEGU_DEPTH_TEST);
  164.     sceGuEnable (SCEGU_BLEND);
  165.     sceGuEnable (SCEGU_DITHER);
  166.     sceGuEnable (SCEGU_TEXTURE);
  167.     sceGuEnable (SCEGU_CULL_FACE);
  168.     sceGuEnable (SCEGU_CLIP_PLANE);
  169.     sceGuEnable (SCEGU_CULL_PATCH);
  170.     sceGuEnable (SCEGU_NORMAL_REVERSE_PATCH);
  171.     sceGuFrontFace (SCEGU_CCW);
  172.     sceGuShadeModel (SCEGU_SMOOTH);
  173.     sceGuAlphaFunc (SCEGU_GEQUAL, 0, 255);
  174.     sceGuDepthFunc (SCEGU_GEQUAL);
  175.     sceGuBlendFunc (SCEGU_ADD, SCEGU_SRC_ALPHA, SCEGU_ONE_MINUS_SRC_ALPHA, 0, 0);
  176.     sceGuTexFilter (SCEGU_LINEAR_MIPMAP_LINEAR, SCEGU_LINEAR);
  177.     sceGuTexFunc (SCEGU_TEX_MODULATE, SCEGU_RGBA);
  178.     sceGuTexWrap (SCEGU_REPEAT, SCEGU_REPEAT);
  179.     sceGuPatchDivide (4, 4);
  180. }
  181. void swapBuffers(void)
  182. {
  183.     sceGuSync (SCEGU_SYNC_FINISH, SCEGU_SYNC_WAIT);
  184.     sceDisplayWaitVblankStart ();
  185.     sceGuSwapBuffers ();
  186. }
  187. void drawDog(float x, float y, float z)
  188. {
  189.     // Currently unused local variables: could be used for direction of character
  190.     // or something?
  191.     float _x=x, _y=y, _z=z;
  192.     // This makes our hero jump if the player has hit the triangle key:
  193.     if(JUMP==true)
  194.     {
  195.         dogJump();
  196.     }
  197.     sceGumMatrixMode (SCEGU_MATRIX_WORLD);
  198.     sceGumLoadIdentity ();
  199.     sceGumTranslate (&translateDog);
  200.     sceGumRotateY (SCEGU_RAD(rotationDog.y));
  201.     // I don't think this is needed:
  202.     // sceGumRotateX (SCEGU_RAD(rotationDog.x));
  203.     // Draw model
  204.     ScePspFMatrix4 m;
  205.     sceGumScale (&scaleDog);
  206.     sceGumStoreMatrix (&m);
  207.     sceGmoModelSetWorldMatrix (model1, &m);
  208. #ifdef DO_ANIMATION
  209.     // Will only animate the Dog if the relevant user interactions are set:
  210.     if(CTRL)
  211.     {
  212.         sceGmoModelAnimate (model1, framerate/60.00f);
  213.     }
  214. #endif
  215.     // Does update stuffs:
  216.     sceGmoModelUpdate (model1);
  217.     sceGmoModelDraw (model1);
  218.     //sceGmoModelUpdate (model2);
  219.     //sceGmoModelDraw (model2);
  220. }
  221. //----------------------------------------------------------------
  222. //  load and unload
  223. //----------------------------------------------------------------
  224. bool loadDogModel (int argc, char **argv)
  225. {
  226.     const char *filename=(argc<2)?DOG_FILE : argv[1];
  227.     //  Load model from file
  228.     int *data, size;
  229.     if (!loadFile(filename, &data, &size ))
  230.     {
  231.         data=0;
  232.         size=0;
  233.     }
  234.     //  Create models
  235.     model1=sceGmoModelCreate (0);
  236.     sceGmoModelLoadFile (model1, data, size, 0);
  237.     sceGmoModelSetOptionFlags (model1, SCEGMO_OPTION_MULTIPLY_WORLD, 0);
  238. #ifdef DO_ANIMATION
  239.     sceGmoModelSetCurrentMotion (model1, 0, 0.0f);
  240. #endif
  241.     //  Initial position of dog
  242.     translateDog=(ScePspFVector3){ 0, -5, 8 };
  243.     rotationDog=(ScePspFVector3){ 0, 0, 0 };
  244.     scaleDog=(ScePspFVector3){ 0.5, 0.5, 0.5 };
  245.     // Free up data read from file
  246.     free (data);
  247.     return (model1!=0);
  248. }
  249. void unloadDogModel (void)
  250. {
  251.     sceGmoModelDelete (model1);
  252.     model1=0;
  253. }
  254. // Here's our jump routine... the physics could be improved to make it more
  255. // 'realistic', as you see dogs running around on their hind legs and jumping
  256. // from them all of the time, right? But for the purposes of a video game engine
  257. // it could be improved...
  258. void dogJump (void)
  259. {
  260.     // Checks if the Dog has reached the highest point yet:
  261.     if(translateDog.y>-1.00)
  262.     {
  263.         // if so, make him return to the ground by changing the jump parameter:
  264.         jump=-0.5;
  265.     }
  266.     // if the dog has reached the floor, we want to stop calling this routine
  267.     // and set the Dog to walk along the default floor co-ordinates:
  268.     if(translateDog.y<-5)
  269.     {
  270.         translateDog.y=-5;
  271.         JUMP=false;
  272.         jump=0.5;
  273.         return;
  274.     }
  275.     // This 'translates' the Dog's position on the Y plane, ie, looks as though he's
  276.     // jumping or something:
  277.     translateDog.y+=jump;
  278. }
  279. // Here's our spooky Castle:
  280. void drawCastle(float x, float y, float z)
  281. {
  282.     // Again, I could think of a use for these - but leave them in the TO DO list:
  283.     float _x=x, _y=y, _z=z;
  284.     sceGumMatrixMode (SCEGU_MATRIX_WORLD);
  285.     sceGumLoadIdentity ();
  286.     sceGumTranslate (&translateCas);
  287.     sceGumRotateY (SCEGU_RAD(rotationCas.y));
  288.     sceGumRotateX (SCEGU_RAD(rotationCas.x));
  289.     // Draw model
  290.     ScePspFMatrix4 m;
  291.     sceGumScale (&scaleCas);
  292.     sceGumStoreMatrix (&m);
  293.     sceGmoModelSetWorldMatrix (model2, &m);
  294.     sceGmoModelUpdate (model2);
  295.     sceGmoModelDraw (model2);
  296. }
  297. // Loads the castle into the memory, or adds it to the file or something:
  298. bool loadCastleModel (int argc, char **argv)
  299. {
  300.     const char *filename=(argc<2)?CASTLE : argv[1];
  301.     //  Load model from file
  302.     int *data, size;
  303.     if (!loadFile(filename, &data, &size ))
  304.     {
  305.         data=0;
  306.         size=0;
  307.     }
  308.     //  Create models
  309.     model2=sceGmoModelCreate (0);
  310.     sceGmoModelLoadFile (model2, data, size, 0);
  311.     sceGmoModelSetOptionFlags (model2, SCEGMO_OPTION_MULTIPLY_WORLD, 0);
  312.     //  Initial position of Castle
  313.     translateCas=(ScePspFVector3){ 0, -5, 0 };
  314.     rotationCas=(ScePspFVector3){ 0, 0, 0 };
  315.     scaleCas=(ScePspFVector3){ 2, 2, 2 } ;
  316.     // Free up data read from file
  317.     free (data);
  318.     return (model2!=0);
  319. }
  320. // Does the unload bit:
  321. void unloadCastleModel (void)
  322. {
  323.     sceGmoModelDelete (model2);
  324.     model2=0;
  325. }
  326. bool loadFile (const char *filename, int **buf, int *size)
  327. {
  328.     char fullpath [256];
  329.     snprintf (fullpath, sizeof(fullpath), "host0:%s", filename);
  330.     SceUID fd=sceIoOpen (fullpath, SCE_O_RDONLY, 0777);
  331.     if (fd<0)
  332.     {
  333.         return false;
  334.     }
  335.     *size=sceIoLseek (fd, 0, SCE_SEEK_END);
  336.     if (*size<=0)
  337.     {
  338.         sceIoClose (fd);
  339.         return false;
  340.     }
  341.     sceIoLseek (fd, 0, SCE_SEEK_SET);
  342.     *buf=(int*)malloc(*size);
  343.     if (*buf==0)
  344.     {
  345.         sceIoClose (fd);
  346.         return false;
  347.     }
  348.     sceIoRead (fd, (void *)*buf, (unsigned int)*size);
  349.     sceIoClose (fd);
  350.     return true;
  351. }
  352. // Here's where much of the game mechanics are altered... well, there's not much
  353. // of a game, but it does some of what a real game would do:
  354. static void readPad (void)
  355. {
  356.     SceCtrlData buf[8];
  357.     SceInt32 ret    =sceCtrlReadBufferPositive(buf, 8);
  358.     SceUInt32 padd  =(ret!=0)?buf[0].Buttons:0;
  359.     // This is set just in case there is no control inputs from the user,
  360.     // so in other words, the default is set and that means the animation
  361.     // on the Dog is stopped. Of course, this boolean is made true on certain
  362.     // user interactions as below:
  363.     if (CTRL==true)
  364.     {
  365.         CTRL=false;
  366.     }
  367.     // CTRL will now be set true if the dog requires animation
  368.     // This moves the Dog 'towards' the Castle:
  369.     if (padd & SCE_CTRL_UP)
  370.     {
  371.         if (translateCas.z<4)
  372.         {
  373.             translateCas.z++;
  374.         }
  375.         // Animation is set to true even if the Dog is at the Castle
  376.         // door or 'in' the castle walls - that latter is a bug I need to
  377.         // work out how to fix!
  378.         CTRL=true;
  379.     }
  380.     // This moves the Dog away from the castle:
  381.     if (padd & SCE_CTRL_DOWN)
  382.     {
  383.         if (translateCas.z>-16)
  384.         {
  385.             translateCas.z--;
  386.         }
  387.         CTRL=true;
  388.     }
  389.     // This 'rotates' the Dog around the Y axis 'clockwise':
  390.     if (padd & SCE_CTRL_LEFT)
  391.     {
  392.         rotationDog.y-=2;
  393.         CTRL=true;
  394.     }
  395.     // This 'rotates' the Dog around the Y axis 'andi-clockwise':
  396.     if (padd & SCE_CTRL_RIGHT) 
  397.     {
  398.         rotationDog.y+=2;
  399.         CTRL=true;
  400.     }
  401.     // Select flips between the two frame rates:
  402.     if (padd & SCE_CTRL_SELECT)
  403.     {
  404.         if (framerate==1)
  405.         {
  406.             framerate=2;
  407.         }
  408.         else
  409.             framerate=1;
  410.     }
  411.     // The top 'L' button basically moves the castle, but gives the impression
  412.     // that the Dog is walking left as you're looking at the screen:
  413.     if (padd & SCE_CTRL_L)
  414.     {
  415.         if(translateCas.x<20)
  416.         {
  417.             translateCas.x+=0.25;
  418.         }
  419.         CTRL=true;
  420.     }
  421.     // And the top 'R' button does the opposite as above:
  422.     if (padd & SCE_CTRL_R)
  423.     {
  424.         if(translateCas.x>-16)
  425.         {
  426.             translateCas.x-=0.25;
  427.         }
  428.         CTRL=true;
  429.     }
  430.     // Triangle is used for jumping, so it sets the relevant boolean true:
  431.     if (padd & SCE_CTRL_TRIANGLE)
  432.     {
  433.         JUMP=true;
  434.     }
  435.     // The Circle will move the camera on the X axis (hold down and it will
  436.     // go both ways once it's reached it's limits on each side):
  437.     if (padd & SCE_CTRL_CIRCLE)
  438.     {
  439.         camx=camx+xdirection;
  440.         if(camx>12)
  441.         {
  442.             xdirection=-0.5;
  443.         }
  444.         if(camx<-12)
  445.         {
  446.             xdirection=0.5;
  447.         }
  448.     }
  449.     // Square does the same as Circle but on the Y axis for the camera view:
  450.     if (padd & SCE_CTRL_SQUARE)
  451.     {
  452.         camy=camy+ydirection;
  453.         if(camy>12)
  454.         {
  455.             ydirection=-0.5;
  456.         }
  457.         if(camy<-12)
  458.         {
  459.             ydirection=0.5;
  460.         }
  461.     }
  462.     // And the cross ('X') is used to zoom in and out of the scene (again, has a
  463.     // bounce method when it reaches it's limits):
  464.     if (padd & SCE_CTRL_CROSS)
  465.     {
  466.         camz=camz+zoomdirection;
  467.         if(camz>75)
  468.         {
  469.             zoomdirection=-0.5;
  470.         }
  471.         if(camz<20)
  472.         {
  473.             zoomdirection=0.5;
  474.         }
  475.     }
  476.     // The Start button will reset the camera to default:
  477.     if (padd & SCE_CTRL_START)
  478.     {
  479.         framerate=2; dogx=0.00f; dogy=0.00f; dogz=0.00f;
  480.         casx=0.00f, casy=0.00f, casz=0.00f;
  481.         camx=0; camy=1; camz=50.00f;
  482.         xdirection=0.5, ydirection=0.5;
  483.     }
  484. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement