VgaGames 3 - VgaGames3-object man-pages

[.. upper level ..]

VgaGames3-object functions

Objects of the game can be set and administered by VgaGames using VgaGames3-objects.
Each VgaGames3-object has individual functions for instantiating, running, drawing, being hit, ...
Furthermore object-to-objects have to be defined with functions for collision or quitting.

E.g. a spaceship is an VgaGames3-object and its enemies is an VgaGames3-object.
There is only one instance of the spaceship-object, but there are many instances of the enemy-object.
For the interaction of both objects one object-to-object must be defined for the two objects (spaceship and enemy),
in which the collision-function destroys the enemy-instance and perhaps the spaceship-instance.

It may be similar to a SQL-database.
VgaGames3-objects can be compared to database-tables.
The objects have their properties defined as a structure in a H-file to be included.
Object-to-object-functions of VgaGames3-objects can be compared to links between two database-tables.
They have access to the properties of both objects (by including both H-files)
and manage interaction between them, e.g. collision, perhaps by modifying some variables of the object-instances.

VgaGames3-objects are referenced via an object-ID (string), see element oid of struct vg3_ofunc_object.
Object-instances are referenced via an instance-ID (positive integer), which will be set in VG3_ofunc_objlist_insert().

Static variables of an VgaGames3-object can be initialized and destructed
by its optional init_dest_* function (see ofunc_new()).
This function is called once by ofunc_new() for initialization, and by VG3_ofunc_free() for destruction.

Usually VgaGames3-objects are used in combination with Collision-detection functions
and the object-moving-and-collision-detecting function VG3_move_object_check_collision().

There are also object-managing functions, which can mainly be used to create new object-instances.
They are referenced by the object-ID of the object they manage.
Object-managing does not instantiate itself.

Each object and each object-management of each object-ID has an individual seed-value,
which can be used to create random numbers with VG3_nw_random_getnext().
When using network, these seed-values must be renewed after a VG3_nw_connect()
via VG3_ofunc_reset_seeds() to keep them in sync with all network-clients.


Example

  /* A pseudo-game with an object SUNNYBOY
   * which moves from left to right.
   * When used without object-managing (use_mgmt = 0), then the game exits.
   * When used with object-managing (use_mgmt = 1),
   * then this happens three times before the game exits.
   */

  

game.h

#ifndef GAME_H_ #define GAME_H_ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> #include <errno.h> #include <stdarg.h> #include <vgagames3.h> #define OID_SUNNYBOY "SUNNYBOY" struct game { /* individual game structure */ struct vg3_window *wstruct; /* window structure */ int w, h; /* size of window */ struct vg3_ofunc *ofstruct; /* common VgaGames3-object structure */ }; #endif

sunnyboy.h

#ifndef SUNNYBOY_H_ #define SUNNYBOY_H_ struct sboy { /* private structure for sunnyboy object */ int xm, ym; /* position on window (centered) */ struct vg3_image *img; /* sunnyboy image */ }; #endif

sunnyboy.c

/* sunnyboy object */ #include "game.h" #include "sunnyboy.h" static struct vg3_ofunc_object * f_new(void *, unsigned int, ...); static void f_free(void *, struct vg3_ofunc_object *); static void f_run(void *, struct vg3_ofunc_object *); static void f_draw(void *, struct vg3_ofunc_object *); /* fill out the passed structure for object-functions of this VgaGames3-object */ void getofc_sboy(struct vg3_ofunc_objfunc *ofc) { if (ofc == NULL) { return; } snprintf(ofc->oid, sizeof(ofc->oid), "%s", OID_SUNNYBOY); ofc->f_new = f_new; ofc->f_free = f_free; ofc->f_run = f_run; ofc->f_draw = f_draw; /* we don't need f_data */ } /* now define the functions */ /* create a new object-instance */ static struct vg3_ofunc_object * f_new(void *vgame, unsigned int parent_objid, ...) { /* vgame: individual game structure, here: struct game * * parent_objid: we don't need it here either */ struct game *gstruct = (struct game *)vgame; struct vg3_ofunc_object *objp; struct sboy *gobj; va_list ap; objp = calloc(1, sizeof(*objp)); /* create VgaGames3-object structure for this instance */ gobj = calloc(1, sizeof(*gobj)); /* create private structure for this instance */ /* set private structure */ /* as variadic parameter we got the position xm and ym */ va_start(ap, parent_objid); gobj->xm = va_arg(ap, int); gobj->ym = va_arg(ap, int); va_end(ap); /* load image */ gobj->img = VG3_image_load(gstruct->wstruct, "sunnyboy.bmp", 0); /* set VgaGames3-object structure */ snprintf(objp->oid, sizeof(objp->oid), "%s", OID_SUNNYBOY); objp->subid = 0; objp->drawlevel = 1; objp->instanceid = 0; /* will be set in VG3_ofunc_objlist_insert() */ objp->ostruct = gobj; /* set private structure into VgaGames3-object structure */ /* insert instance into list of object-instances */ VG3_ofunc_objlist_insert(gstruct->ofstruct, objp); return objp; } /* free an object-instance */ static void f_free(void *vgame, struct vg3_ofunc_object *objp) { struct game *gstruct = (struct game *)vgame; struct sboy *gobj; gobj = (struct sboy *)objp->ostruct; /* remove instance from list of object-instances */ VG3_ofunc_objlist_remove(gstruct->ofstruct, objp); /* free instance */ VG3_image_unload(gstruct->wstruct, gobj->img); free(gobj); free(objp); } /* move an object-instance */ static void f_run(void *vgame, struct vg3_ofunc_object *objp) { struct game *gstruct = (struct game *)vgame; struct sboy *gobj; gobj = (struct sboy *)objp->ostruct; /* very simple: just move to the right, * normally we would check keystrokes * or move it according to an algorithm */ gobj->xm++; /* remove sunnyboy if it has reached the right border */ if (gobj->xm > gstruct->w) { f_free(vgame, objp); } } /* draw an object-instance */ static void f_draw(void *vgame, struct vg3_ofunc_object *objp) { struct game *gstruct = (struct game *)vgame; struct sboy *gobj; gobj = (struct sboy *)objp->ostruct; VG3_image_copy(gstruct->wstruct, NULL, gobj->img, gobj->xm, gobj->ym, NULL, 0); }

game.c

/* game */ #include "game.h" extern struct vg3_ofunc * ofunc_new(void); int main(int argc, char **argv) { const int use_mgmt = 1; /* if 1 use object-management for sunnyboy */ struct game gstruct; /* open window */ gstruct.wstruct = VG3_window_new(argv[0], VGAG3_VGAVERSION_LOW, VGAG3_WINSCALE_NOSCALE); if (gstruct.wstruct == NULL) { fprintf(stderr, "%s\n", VG3_error()); exit(1); } /* get window size */ VG3_window_getsize(gstruct.wstruct, &gstruct.w, &gstruct.h); /* create the common VgaGames3-object structure */ gstruct.ofstruct = ofunc_new(); if (use_mgmt) { /* activate sunnyboy-object-management with 3 sunnyboy-instances */ if (VG3_ofunc_mgmt_activate(gstruct.ofstruct, &gstruct, OID_SUNNYBOY, 3) != 0) { fprintf(stderr, "%s\n", VG3_error()); goto endgame; } } else { /* create instance of sunnyboy object and put it to the left */ const struct vg3_ofunc_objfunc *ofc; ofc = VG3_ofunc_get_objfunc(gstruct.ofstruct, OID_SUNNYBOY); if (ofc == NULL) { fprintf(stderr, "Need sunnyboy-object, but not found\n"); goto endgame; } if (ofc->f_new(&gstruct, 0, 0, gstruct.h / 2) == NULL) { fprintf(stderr, "%s\n", VG3_error()); goto endgame; } } /* game-loop */ for (;;) { if (VG3_inputevent_update(gstruct.wstruct)) { break; } VG3_draw_clear(gstruct.wstruct, NULL, VGAG3_COLOR_BLACK); if (use_mgmt) { /* execute object-managing */ VG3_ofunc_mgmt_run(gstruct.ofstruct, &gstruct); } /* execute run-function of loaded object-instances */ VG3_ofunc_objlist_call_run(gstruct.ofstruct, &gstruct); /* execute draw-function of loaded object-instances */ VG3_ofunc_objlist_call_draw(gstruct.ofstruct, &gstruct); VG3_window_update(gstruct.wstruct, 0, 0); VG3_wait_time(20); if (use_mgmt) { /* if there is no remaing sunnyboy, quit */ if (VG3_ofunc_mgmt_data(gstruct.ofstruct, &gstruct, OID_SUNNYBOY, NULL) == 0) { break; } } else { /* if sunnyboy has gone, quit game */ if (VG3_ofunc_objlist_find_obj(gstruct.ofstruct, OID_SUNNYBOY, NULL) < 1) { break; } } } /* unload and free still existing object-instances */ VG3_ofunc_objlist_call_free(gstruct.ofstruct, &gstruct, NULL); if (use_mgmt) { /* deactivate still existing object-managements */ VG3_ofunc_mgmt_deactivate(gstruct.ofstruct, &gstruct, NULL); } /* free common VgaGames3-object structure */ VG3_ofunc_free(gstruct.ofstruct); endgame: /* close window */ VG3_window_free(gstruct.wstruct); exit(0); }

sunnyboy_mgmt.c (only needed when in game.c: use_mgmt = 1)

/* sunnyboy object-management */ #include "game.h" /* static structure for this object-managing */ static struct { int remaining; /* how many sunnyboys to show */ } sunnyboy_mgmt; static int f_activate(void *, struct vg3_ofunc *, va_list); static void f_deactivate(void *, struct vg3_ofunc *); static void f_run(void *, struct vg3_ofunc *); static int f_data(void *, struct vg3_ofunc *, void *); /* fill out the passed structure for object-management-functions of this VgaGames3-object */ void getofmgmt_sboy(struct vg3_ofunc_ofmgmt *ofm) { if (ofm == NULL) { return; } snprintf(ofm->oid, sizeof(ofm->oid), "%s", OID_SUNNYBOY); ofm->f_activate = f_activate; ofm->f_deactivate = f_deactivate; ofm->f_run = f_run; ofm->f_data = f_data; } /* now define the functions */ /* activate the managing of sunnyboys, pass number of them to show */ static int f_activate(void *vgame, struct vg3_ofunc *ofstruct, va_list ap) { /* vgame: individual game structure, here: struct game, but we don't need it */ struct game *gstruct = (struct game *)vgame; (void)gstruct; if (ofstruct == NULL) { VG3_seterror(EINVAL, strerror(EINVAL)); return -1; } /* as variadic parameter we got the number of sunnyboys, * we put it into our static structure */ sunnyboy_mgmt.remaining = va_arg(ap, int); return 0; } /* deactivate the managing of sunnyboys */ static void f_deactivate(void *vgame, struct vg3_ofunc *ofstruct) { /* vgame: individual game structure, here: struct game, but we don't need it */ struct game *gstruct = (struct game *)vgame; (void)gstruct; if (ofstruct == NULL) { return; } /* now we clean up our static structure */ sunnyboy_mgmt.remaining = 0; } /* execute managing of sunnyboy-instances, * creating a new one, if no sunnyboy is active */ static void f_run(void *vgame, struct vg3_ofunc *ofstruct) { /* vgame: individual game structure, here: struct game */ struct game *gstruct = (struct game *)vgame; if (ofstruct == NULL) { return; } /* we check whether a sunnyboy is still active, * if not, we create a new one, * until sunnyboy_mgmt.remaining is decremented to 0 */ if (VG3_ofunc_objlist_find_obj(ofstruct, OID_SUNNYBOY, NULL) == 0) { if (sunnyboy_mgmt.remaining > 0) { const struct vg3_ofunc_objfunc *ofc; ofc = VG3_ofunc_get_objfunc(ofstruct, OID_SUNNYBOY); if (ofc == NULL) { sunnyboy_mgmt.remaining = 0; return; } if (ofc->f_new(vgame, 0, 0, gstruct->h / 2) == NULL) { /* create sunnyboy-instance */ fprintf(stderr, "%s\n", VG3_error()); sunnyboy_mgmt.remaining = 0; return; } sunnyboy_mgmt.remaining--; printf("New sunnyboy-instance created, remaining: %d\n", sunnyboy_mgmt.remaining); } } } /* return number of remaining sunnyboys including the active one */ static int f_data(void *vgame, struct vg3_ofunc *ofstruct, void *vdata) { int retw; /* vgame: individual game structure, here: struct game, but we don't need it */ struct game *gstruct = (struct game *)vgame; (void)gstruct; /* we don't need vdata either */ (void)vdata; if (ofstruct == NULL) { return 0; } /* add to the number of remaining sunnyboys the active one, if existing */ retw = VG3_ofunc_objlist_find_obj(ofstruct, OID_SUNNYBOY, NULL); retw += sunnyboy_mgmt.remaining; return retw; }

Makefile

CFLAGS = -W -Wall -O2 VGAG_CFLAGS = `vgagames3-config --cflags` VGAG_LIBS = `vgagames3-config --libs` game: ofunc.o game.o sunnyboy.o sunnyboy_mgmt.o $(CC) $(CFLAGS) ofunc.o game.o sunnyboy.o sunnyboy_mgmt.o $(VGAG_LIBS) -o game # create ofunc_new() ofunc.c: vg3-objfunc-create-cfile >ofunc.c ofunc.o: ofunc.c $(CC) $(CFLAGS) $(VGAG_CFLAGS) -c ofunc.c game.o: game.c game.h $(CC) $(CFLAGS) $(VGAG_CFLAGS) -c game.c sunnyboy.o: sunnyboy.c sunnyboy.h game.h $(CC) $(CFLAGS) $(VGAG_CFLAGS) -c sunnyboy.c sunnyboy_mgmt.o: sunnyboy_mgmt.c game.h $(CC) $(CFLAGS) $(VGAG_CFLAGS) -c sunnyboy_mgmt.c clean: rm -f game game.o sunnyboy.o sunnyboy_mgmt.o ofunc.o ofunc.c