VgaGames4

VgaGames4 - object man-pages

[.. upper level ..]

# Object functions

Game objects A game object represents certain figures in a game, like spaceships, shots, walls and so on. It is referenced by an object-ID, which is a user-given unique string. Each game object can have one or more object-instances, e.g. many enemy-spaceships of the same type (object), a lot of shots of the same type (object). Object-instances are referenced by an instance-ID, which is a system-created unique number. An object consists of - an exported function to create new object-instances - an internal structure of individual data for each object-instance - internal functions to deal with the object-instances - may have more exported functions for the object The exported creating-function - must create and set the internal structure of individual data - must call vg4->object->create() which returns a created structure of struct VG_Object - must set the function pointers of the struct VG_Object to its internal functions to deal with the object-instances - should return the instance-ID of the created struct VG_Object The function vg4->object->instance_getobj() returns the object-instance from its instance-ID. Object-management Each object can have an object-management, if needed, for creating and destroying object-instances by non-user actions, e.g. for random-generated object-instances of an enemy-spaceship. An object-management consists of - an exported function to create the object-management for an object - an internal structure of data for the object-management (optional) - internal functions to deal with the object-management The exported creating-function - must set the internal structure of data (optional) - must call vg4->object->mgmt_create() which returns a created structure of struct VG_ObjMgmt - must set the function pointers of the struct VG_ObjMgmt to its internal functions to deal with the object-management - should return a boolean whether it was successful, as the created struct VG_ObjMgmt is internally saved and not needed elsewhere Dealing with object-instances and object-management To deal with object-instances and object-management, their internal functions must be called. For object-instances - the internal function f_run() for moving the instance is called by vg4->object->call_run() which shall be called once per game-loop - the internal function f_draw() for drawing the instance is called by vg4->object->call_draw() which shall be called once per game-loop after f_run() - the internal function f_data() for exchanging data is called by vg4->object->call_data() which can be called for one object-instance as needed - the internal function f_free() for freeing the internal structure of data is called when the object-instance is destroyed by vg4->object->destroy() - the internal function f_childexit() for informing the parent that a child is dead is automatically called when a child-instance is destroyed - the internal function f_signal() for sending a signal-number is called by vg4->object->call_signal() or vg4->object->call_signal_objid() None of these internal functions must exist. For object-management - the internal function f_run() for managing object-instances is called by vg4->object->call_mgmt_run() which shall be called once per game-loop before vg4->object->call_run() - the internal function f_data() for exchanging data is called by vg4->object->call_mgmt_data() which can be called as needed - the internal function f_free() for freeing internal data is called when the object-management is destroyed by vg4->object->mgmt_destroy() None of these internal functions must exist. Collision of object-instances To use object-instances with collision they must be - inserted into a collision-tag with vg4->collision->insert() when they are created - removed from the collision-tag with vg4->collision->remove() when they are destroyed, which is done automatically by vg4->object->destroy() When moving they must be updated and checked for collisions with vg4->collision->setpos(). This is as collisions are treated as usual. But when there are many objects it becomes confusing to assign the several found collisions to the right actions. There may be different actions for - a shot hits my spaceship - my shot hits an enemy-spaceship - a shot hits another shot - an enemy-spaceship hits my spaceship - and so on Object-collision-functions solve this problem: - there must exist for each hit-variation a collision-function - these collision-functions must be registered for the two objects they act for, using vg4->object->collision_add() before the game-loop - during the game-loop the found collisions are given to vg4->object->collision_call() which chooses the right collision-functions to be called See also vg4->misc->move_and_check_collisions() for moving and checking for collisions.

- Enumerations and Structures
- struct VG_Object
- struct VG_ObjMgmt
- Objects
- vg4->object->create()
  Create an object-instance.
- vg4->object->destroy()
  Destroy an object-instance.
- vg4->object->destroy_objid()
  Destroy all object-instances of an object-ID.
- vg4->object->destroy_except()
  Destroy object-instances of all object-IDs except the passed ones.
- vg4->object->destroyall()
  Destroy all object-instances.
- vg4->object->instance_getobj()
  Return the object-instance of an instance-ID.
- vg4->object->has_instances()
  Return whether an object-ID has one or more instances.
- vg4->object->list()
  Return a list of instance-IDs for an object-ID (or for all objects).
- Object-management
- vg4->object->mgmt_create()
  Create an object-management for an object.
- vg4->object->mgmt_destroy()
  Destroy an object-management.
- vg4->object->mgmt_destroyall()
  Destroy all object-managements.
- Calling object- and object-management functions
- vg4->object->call_run()
  Call object-function f_run() for all object-instances.
- vg4->object->call_draw()
  Call object-function f_draw() for all object-instances.
- vg4->object->call_data()
  Call object-function f_data() for an object-instance.
- vg4->object->call_signal()
  Call object-function f_signal() for an object-instance.
- vg4->object->call_signal_objid()
  Call object-function f_signal() for all instances of an object.
- vg4->object->call_mgmt_run()
  Call object-management-function f_run() for all object-managements.
- vg4->object->call_mgmt_data()
  Call object-function f_data() for an object-management.
- Object collisions
- vg4->object->collision_add()
  Add a collision-function for two object-IDs.
- vg4->object->collision_call()
  Call a collision-function for each given collision.
- vg4->object->collision_destroyall()
  Destroy all settings with collision-functions.

## Example

Object-instance coming
Object-instance colliding
Object-instance going

###

    Same example as in collision:
      Move an object-instance to another, change colors of both while they collide
    But here solved with two objects RECTANGLE1 and RECTANGLE2
    and a collision-function for both objects.

    The main program consists of:
     - example.c
     - example.h
         which contains the private game structure
     - objnew.h
         (included by example.h)
         for the exported functions to create new object-instances
     - objcoll.h
         (included by example.h)
         for the exported functions for collisions of two objects

    The object RECTANGLE1 consists of:
     - obj-rectangle1.c
     - obj-rectangle1.h
         which contains the private structure for the object

    The object RECTANGLE2 consists of:
     - obj-rectangle2.c
     - obj-rectangle2.h
         which contains the private structure for the object

    The collision-function RECTANGLE1 against RECTANGLE2 consists of:
     - objcoll-rectangle1-rectangle2.c
         which includes the header files of both objects
         to have access to their private structures

    example.h

    #ifndef EXAMPLE_H_
    #define EXAMPLE_H_

    #include <vgagames4.h>

    /* include export-functions to create new object-instances */
    #include "objnew.h"

    /* include export-functions for collisions of two objects */
    #include "objcoll.h"

    /* private structure of the game */
    struct s_game {
      unsigned int coll_tag;  /* collision-tag */
    };

    #endif /* EXAMPLE_H_ */

    example.c

    /* move an object-instance to another, change colors of both while they collide */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include "example.h"

    /* private structure of the game */
    struct s_game sgame;

    int main(int argc, char **argv) {
      (void)argc; (void)argv;

      /* initialize and open window */
      if (!VG_init("test")) { exit(1); }
      if (!vg4->window->open(VG_WINDOW_SIZE_LOW, VG_WINDOW_SCALE_BEST)) { VG_dest(); exit(1); }

      /* add object-collision functions */
      vg4->object->collision_add("RECTANGLE1", "RECTANGLE2", objcoll_RECTANGLE1_RECTANGLE2);

      /* initialize game-structure */
      memset(&sgame, 0, sizeof(sgame));

      /* create collision-tag */
      sgame.coll_tag = vg4->collision->create(NULL, 0, 0);

      /* create object-instances */
      if (objnew_RECTANGLE1(&sgame) == 0) { VG_dest(); exit(1); }
      if (objnew_RECTANGLE2(&sgame) == 0) { VG_dest(); exit(1); }

      /* game loop */
      for (;;) {
        if (!vg4->input->update(VG_TRUE)) { break; }

        vg4->window->clear();

        /* call f_run() of all object-instances */
        if (!vg4->object->call_run(&sgame)) { break; }

        /* call f_draw() of all object-instances */
        vg4->object->call_draw(&sgame);

        vg4->window->flush();
        vg4->misc->wait_time(30);
      }

      /* destroy and exit */
      VG_dest();
      exit(0);
    }

    objnew.h

    #ifndef OBJNEW_H_
    #define OBJNEW_H_

    /* export-functions to create new object-instances */
    extern unsigned int objnew_RECTANGLE1(void *);
    extern unsigned int objnew_RECTANGLE2(void *);

    #endif /* OBJNEW_H_ */

    obj-rectangle1.h

    #ifndef OBJ_RECTANGLE1_H_
    #define OBJ_RECTANGLE1_H_

    #include "example.h"

    /* private structure for object RECTANGLE1 */
    struct sobj_rectangle1 {
      struct VG_Rect rect;
      int color;
    };

    #endif /* OBJ_RECTANGLE1_H_ */

    obj-rectangle1.c

    /* object "RECTANGLE1" */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include "obj-rectangle1.h"

    #define OBJID "RECTANGLE1"

    unsigned int objnew_RECTANGLE1(void *);

    static void f_free(void *, void *);
    static VG_BOOL f_run(void *, struct VG_Object *);
    static void f_draw(void *, struct VG_Object *);

    /* export-function to create a new object-instance of "RECTANGLE1" */
    unsigned int
    objnew_RECTANGLE1(void *vgame)
    {
      const int coll_percent = 100;
      struct s_game *sgame = (struct s_game *)vgame;
      struct VG_Object *objp;
      struct sobj_rectangle1 *objvars;
      int winw, winh;

      if (sgame == NULL) { return 0; }

      vg4->window->getsize(&winw, &winh);

      /* allocate private struct */
      objvars = calloc(1, sizeof(*objvars));
      if (objvars == NULL) { return 0; }

      /* set private struct */
      objvars->rect.x = 0;
      objvars->rect.w = 20;
      objvars->rect.y = winh / 2 - 5;
      objvars->rect.h = 20;
      objvars->color = VG_COLOR_RED;

      /* create object-instance */
      objp = vg4->object->create(OBJID, 0, 0, 1, objvars);

      /* set functions */
      objp->f_free = f_free;
      objp->f_run = f_run;
      objp->f_draw = f_draw;
      /* f_data(), f_childexit() and f_signal() are not needed here */

      /* insert object-instance into collision-tag */
      vg4->collision->insert(sgame->coll_tag, objp->instanceid, &objvars->rect, coll_percent);

      return objp->instanceid;
    }

    /* free private struct of object-instance, called from vg4->object->destroy() */
    static void
    f_free(void *vgame, void *opriv)
    {
      struct sobj_rectangle1 *objvars = (struct sobj_rectangle1 *)opriv;

      (void)vgame;

      /* free private struct */
      free(objvars);
    }

    /* move object-instance, called from vg4->object->call_run() */
    static VG_BOOL
    f_run(void *vgame, struct VG_Object *objp)
    {
      struct s_game *sgame = (struct s_game *)vgame;
      struct sobj_rectangle1 *objvars = (struct sobj_rectangle1 *)objp->opriv;
      int winw, canz, cret;
      struct VG_Coll *collp;

      /* move it one step to the right until window-boundary */
      vg4->window->getsize(&winw, NULL);
      if (++objvars->rect.x == winw) { return VG_FALSE; }  /* window-boundary: end of game */

      /* update object-instance in collision-tag and check for collisions */
      canz = vg4->collision->setpos(sgame->coll_tag, objp->instanceid, &objvars->rect, &collp);

      /* call collision-functions and free collision array */
      cret = vg4->object->collision_call(sgame, objp->instanceid, collp, canz);
      if (collp != NULL) { free(collp); }

      if (cret == VG_COLL_RETURN_STOP || cret == VG_COLL_RETURN_STOP_X || cret == VG_COLL_RETURN_STOP_Y) {
        /* if stopped, go back and update object-instance in collision-tag */
        objvars->rect.x--;
        vg4->collision->setpos(sgame->coll_tag, objp->instanceid, &objvars->rect, NULL);
      } else if (cret == VG_COLL_RETURN_DEAD) {
        /* if dead, destroy yourself and return */
        vg4->object->destroy(sgame, objp->instanceid);
        return VG_TRUE;
      }

      return VG_TRUE;
    }

    /* draw object-instance, called from vg4->object->call_draw() */
    static void
    f_draw(void *vgame, struct VG_Object *objp)
    {
      struct sobj_rectangle1 *objvars = (struct sobj_rectangle1 *)objp->opriv;

      (void)vgame;

      /* draw it */
      vg4->window->draw_rect(&objvars->rect, objvars->color, VG_TRUE);
    }

    obj-rectangle2.h

    #ifndef OBJ_RECTANGLE2_H_
    #define OBJ_RECTANGLE2_H_

    #include "example.h"

    /* private structure for object RECTANGLE2 */
    struct sobj_rectangle2 {
      struct VG_Rect rect;
      int color;
    };

    #endif /* OBJ_RECTANGLE2_H_ */

    obj-rectangle2.c

    /* object "RECTANGLE2" */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include "obj-rectangle2.h"

    #define OBJID "RECTANGLE2"

    unsigned int objnew_RECTANGLE2(void *);

    static void f_free(void *, void *);
    static void f_draw(void *, struct VG_Object *);

    /* export-function to create a new object-instance of "RECTANGLE2" */
    unsigned int
    objnew_RECTANGLE2(void *vgame)
    {
      const int coll_percent = 100;
      struct s_game *sgame = (struct s_game *)vgame;
      struct VG_Object *objp;
      struct sobj_rectangle2 *objvars;
      int winw, winh;

      if (sgame == NULL) { return 0; }

      vg4->window->getsize(&winw, &winh);

      /* allocate private struct */
      objvars = calloc(1, sizeof(*objvars));
      if (objvars == NULL) { return 0; }

      /* set private struct */
      objvars->rect.x = winw / 2;
      objvars->rect.w = 20;
      objvars->rect.y = winh / 2;
      objvars->rect.h = 20;
      objvars->color = VG_COLOR_GREEN;

      /* create object-instance */
      objp = vg4->object->create(OBJID, 0, 0, 1, objvars);

      /* set functions */
      objp->f_free = f_free;
      objp->f_draw = f_draw;
      /* f_run(), f_data(), f_childexit() and f_signal() are not needed here */

      /* insert object-instance into collision-tag */
      vg4->collision->insert(sgame->coll_tag, objp->instanceid, &objvars->rect, coll_percent);

      return objp->instanceid;
    }

    /* free private struct of object-instance, called from vg4->object->destroy() */
    static void
    f_free(void *vgame, void *opriv)
    {
      struct sobj_rectangle2 *objvars = (struct sobj_rectangle2 *)opriv;

      (void)vgame;

      /* free private struct */
      free(objvars);
    }

    /* draw object-instance, called from vg4->object->call_draw() */
    static void
    f_draw(void *vgame, struct VG_Object *objp)
    {
      struct sobj_rectangle2 *objvars = (struct sobj_rectangle2 *)objp->opriv;

      (void)vgame;

      /* draw it */
      vg4->window->draw_rect(&objvars->rect, objvars->color, VG_TRUE);
    }

    objcoll.h

    #ifndef OBJCOLL_H_
    #define OBJCOLL_H_

    /* export-functions for collisions of two objects */
    extern int objcoll_RECTANGLE1_RECTANGLE2(void *, unsigned int, struct VG_Coll *);

    #endif /* OBJCOLL_H_ */

    objcoll-rectangle1-rectangle2.c

    /* object-collision "RECTANGLE1" against "RECTANGLE2" (and inverse) */

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include "obj-rectangle1.h"
    #include "obj-rectangle2.h"

    int objcoll_RECTANGLE1_RECTANGLE2(void *, unsigned int, struct VG_Coll *);

    int
    objcoll_RECTANGLE1_RECTANGLE2(void *vgame, unsigned int instanceid, struct VG_Coll *collb)
    {
      struct VG_Object *objp_moving, *objp_hit;
      struct sobj_rectangle1 *objvars_rectangle1;
      struct sobj_rectangle2 *objvars_rectangle2;
      int retw = VG_COLL_RETURN_CONTINUE;

      (void)vgame;

      /* get object-instances */
      objp_moving = vg4->object->instance_getobj(instanceid);
      objp_hit = vg4->object->instance_getobj(collb->instanceid);

      if (strcmp(objp_moving->objid, "RECTANGLE1") == 0) {
        /* RECTANGLE1 is moving, hitting RECTANGLE2 */
        objvars_rectangle1 = (struct sobj_rectangle1 *)objp_moving->opriv;
        objvars_rectangle2 = (struct sobj_rectangle2 *)objp_hit->opriv;
      } else {
        /* RECTANGLE2 is moving, hitting RECTANGLE1 (here impossible as rectangle2 is not moving) */
        objvars_rectangle1 = (struct sobj_rectangle1 *)objp_hit->opriv;
        objvars_rectangle2 = (struct sobj_rectangle2 *)objp_moving->opriv;
      }

      /* modify colors */
      if (collb->type == VG_COLL_TYPE_ENTRY) {  /* entering into collision */
        /* change colors to yellow and white */
        objvars_rectangle1->color = VG_COLOR_YELLOW;
        objvars_rectangle2->color = VG_COLOR_WHITE;
      } else if (collb->type == VG_COLL_TYPE_LEAVE) {  /* leaving collision */
        /* reset colors to default */
        objvars_rectangle1->color = VG_COLOR_RED;
        objvars_rectangle2->color = VG_COLOR_GREEN;
      }

      return retw;
    }

    Makefile

    CFLAGS = -W -Wall -O2
    VGAG_CFLAGS = `vgagames4-config --cflags`
    VGAG_LIBS = `vgagames4-config --libs`

    H_FILES = example.h objnew.h objcoll.h

    example: example.o obj-rectangle1.o obj-rectangle2.o objcoll-rectangle1-rectangle2.o
    	$(CC) $(CFLAGS) example.o obj-rectangle1.o obj-rectangle2.o objcoll-rectangle1-rectangle2.o $(VGAG_LIBS) -o example

    example.o: example.c $(H_FILES)
    	$(CC) $(CFLAGS) $(VGAG_CFLAGS) -c example.c

    obj-rectangle1.o: obj-rectangle1.c obj-rectangle1.h $(H_FILES)
    	$(CC) $(CFLAGS) $(VGAG_CFLAGS) -c obj-rectangle1.c

    obj-rectangle2.o: obj-rectangle2.c obj-rectangle2.h $(H_FILES)
    	$(CC) $(CFLAGS) $(VGAG_CFLAGS) -c obj-rectangle2.c

    objcoll-rectangle1-rectangle2.o: objcoll-rectangle1-rectangle2.c $(H_FILES)
    	$(CC) $(CFLAGS) $(VGAG_CFLAGS) -c objcoll-rectangle1-rectangle2.c

    clean:
    	rm -f example example.o obj-rectangle1.o obj-rectangle2.o objcoll-rectangle1-rectangle2.o