Gamestudio Links
Zorro Links
Newest Posts
Help with plotting multiple ZigZag
by degenerate_762. 04/30/24 23:23
M1 Oversampling
by 11honza11. 04/30/24 08:16
Trading Journey
by howardR. 04/28/24 09:55
Zorro Trader GPT
by TipmyPip. 04/27/24 13:50
Data from CSV not parsed correctly
by jcl. 04/26/24 11:18
AUM Magazine
Latest Screens
The Bible Game
A psychological thriller game
SHADOW (2014)
DEAD TASTE
Who's Online Now
2 registered members (AndrewAMD, SBGuy), 987 guests, and 3 spiders.
Key: Admin, Global Mod, Mod
Newest Members
firatv, wandaluciaia, Mega_Rod, EternallyCurious, howardR
19050 Registered Users
Previous Thread
Next Thread
Print Thread
Rate Thread
Page 1 of 2 1 2
need help with these structs im using #327544
06/07/10 01:50
06/07/10 01:50
Joined: Jul 2008
Posts: 223
Pittsburgh
The_Clyde Offline OP
Member
The_Clyde  Offline OP
Member

Joined: Jul 2008
Posts: 223
Pittsburgh
I'm working on what I think would be a very useful tool for all Gamestudio users... an easy way to create and play back in-engine cutscenes (rendered by A7 instead of loading a video).

On the whiteboard my algorithm and data structures appear to work nicely... but then I tried to implement these and used structs for my data structures and things got weird.

I am not so familiar with the use of structs and the related commands such as malloc and memcopy and others.

I'll detail my playback method and data structs below. It would be really great if somebody could describe to me how to use the structs to accomplish what I've planned. (I've already got code that sort of works but need better knowledge in order to find the bugs)

----------------------------
struct Keyframe
contains
  • activation time of keyframe
  • array of Cues


struct Cue
contains
  • WED entity name
  • start and end positions
  • start and end rotations
  • start and end scale
  • animation name
  • duration of this Cue


Playback Algorithm:
Code:
load keyframes information from text file
put keyframes into an array of keyframes
repeat every frame
{
  if the total time passed has exceeded the start time of the next keyframe
  {
    add all the cues stored in the keyframe to a linked list containing all active cues
  }
  for each cue in the active cues linked list:
  {
    if the total time has passed the end time of the cue
       remove it from the linked list
    otherwise interpolate the position, rotation, scale, and animation of the entity named in the cue based on the current time, and the start and end times of the cue
   }
}
once the end of the keyframe has been reached the scene is ended



At this moment it can load the scene from the text file, but it crashes if I try to make it play any more than one keyframe/cue...

Re: need help with these structs im using [Re: The_Clyde] #327546
06/07/10 03:09
06/07/10 03:09
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline
Expert
EvilSOB  Offline
Expert

Joined: Feb 2008
Posts: 3,232
Australia
Post your existing functions for initialising, saving, and loading your data please,
It will gimme something to work from.

The capture and playback code would help too, but not so important if you
wanna maintain secrecy...




"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Re: need help with these structs im using [Re: EvilSOB] #327547
06/07/10 03:36
06/07/10 03:36
Joined: Jul 2008
Posts: 223
Pittsburgh
The_Clyde Offline OP
Member
The_Clyde  Offline OP
Member

Joined: Jul 2008
Posts: 223
Pittsburgh
Well the capture code is non-existent so far since I haven't made the editor yet... so the only editor I've been using is notepad grin

As for secrecy- its not so important since I've already detailed my algorithm anyway....
Code:
#include <acknex.h>


var cutscene_editmode = 0;
var cutscene_playing = 0;
var cutscene_paused = 0;
var cutscene_time;
var cutscene_keyframe;

typedef struct Cue {
	STRING* entname;
	VECTOR* startpos;
	VECTOR* endpos;
	ANGLE* startang;
	ANGLE* endang;
	VECTOR* startscale;
	VECTOR* endscale;
	STRING* anim; //animation name- or NULL
	var animloops;
	var starttime;
	var duration;
	struct Cue* next; //used when the cue is in the linked list of active cues
	struct Cue* prev;
} Cue; 

typedef struct Keyframe {
	var cuetime;
	var actions_count;
	Cue* actions[64];
} Keyframe;



Keyframe* scene;
Cue* active_cues[300];
var keyframe_count;
Cue* active_cues_head = NULL;

function newCue()
{
	Cue* newcue = malloc(sizeof(Cue));
	memset(newcue,0,sizeof(Cue));
	return newcue;
}

function newKeyframe()
{
	Keyframe* newkeyframe = malloc(sizeof(Keyframe));
	memset(newkeyframe,0,sizeof(Keyframe));
	return newkeyframe;
}

function killCue(Cue* c)
{
	free(c);
}

function killKeyframe(Keyframe* k)
{
	free(k);
}

function loadScene(STRING* filename)
{
	str_cpy(delimit_str," ");
	var filehandle = file_open_read(filename);
	var flop = file_open_write("testt.txt");
	
	var length = file_var_read(filehandle); //first number is number of keyframes to malloc
	file_var_write(flop,length);
	scene = malloc(length * sizeof(Keyframe));
	var i;
	for(i = 0; i < length; i += 1)
	{
		
		memcpy(scene[i],newKeyframe(),sizeof(Keyframe));
		scene[i].cuetime = file_var_read(filehandle);
		scene[i].actions_count = file_var_read(filehandle);
		
	
		if(scene[i].actions_count > 0)
		{
			
			scene[i].actions = malloc(scene[i].actions_count * sizeof(Cue));
			var k;
			for(k = 0; i < scene[i].actions_count; i++)
			{
				
				scene[i].actions[k] = newCue();
				scene[i].actions[k].entname = str_create("#20");
				file_str_read(filehandle,scene[i].actions[k].entname);
				
				scene[i].actions[k].startpos = vector(0,0,0);
				scene[i].actions[k].endpos = vector(0,0,0);
				scene[i].actions[k].startang = vector(0,0,0);
				scene[i].actions[k].endang = vector(0,0,0);
				scene[i].actions[k].startscale = vector(0,0,0);
				scene[i].actions[k].endscale = vector(0,0,0);
				
				scene[i].actions[k].startpos.x = file_var_read(filehandle);
				scene[i].actions[k].startpos.y = file_var_read(filehandle);
				scene[i].actions[k].startpos.z = file_var_read(filehandle);
				scene[i].actions[k].endpos.x = file_var_read(filehandle);
				scene[i].actions[k].endpos.y = file_var_read(filehandle);
				scene[i].actions[k].endpos.z = file_var_read(filehandle);
				scene[i].actions[k].startang.pan = file_var_read(filehandle);
				scene[i].actions[k].startang.tilt = file_var_read(filehandle);
				scene[i].actions[k].startang.roll = file_var_read(filehandle);
				scene[i].actions[k].endang.pan = file_var_read(filehandle);
				scene[i].actions[k].endang.tilt = file_var_read(filehandle);
				scene[i].actions[k].endang.roll = file_var_read(filehandle);
				scene[i].actions[k].startscale.x  = file_var_read(filehandle);
				scene[i].actions[k].startscale.y = file_var_read(filehandle);
				scene[i].actions[k].startscale.z = file_var_read(filehandle);
				scene[i].actions[k].endscale.x = file_var_read(filehandle);
				scene[i].actions[k].endscale.y = file_var_read(filehandle);
				scene[i].actions[k].endscale.z = file_var_read(filehandle);
				file_str_read(filehandle,scene[i].actions[k].anim);
				scene[i].actions[k].animloops = file_var_read(filehandle);
				scene[i].actions[k].starttime = scene[i].cuetime;
				scene[i].actions[k].duration = file_var_read(filehandle);
				
				
				scene[i].actions[k].next = NULL;
				scene[i].actions[k].prev = NULL;
				
			}
		}
		
	}
	file_close(filehandle);
	file_close(flop);
}

function playScene()
{
	cutscene_time = 0;
	cutscene_keyframe = 0;
	cutscene_playing = 1;
	
	var flog = file_open_write("scenelog.txt");
	
	while(cutscene_playing == 1)
	{
		
		while(cutscene_paused) wait(1);
		
		if(scene[cutscene_keyframe].cuetime == 0)
		{
			
			cutscene_playing = 0;
		}
		else{
			
		if(cutscene_time >= scene[cutscene_keyframe].cuetime)
		{
			
			Cue* reader = active_cues_head;
			if(reader != NULL)
			{
				while(reader != NULL && reader.next != NULL)
				{
					reader = reader.next;
				}
			}
				
			var i;
			for(i = 0; i < scene[cutscene_keyframe].actions_count; i += 1)
			{
				
				Cue* thiscue = newCue();
				memcpy(thiscue,scene[cutscene_keyframe].actions[i],sizeof(Cue)); //ERROR HERE
				
				if(reader == NULL)
				{
				
					active_cues_head = thiscue;
					reader = thiscue;
					
				}
				else
				{
					reader.next = thiscue;
					reader.next.prev = reader;
					reader = reader.next;
				}
			}
			
			cutscene_keyframe += 1;
		}
		Cue* reader = active_cues_head;
		while(reader != NULL)
		{
			
			if((reader.starttime + reader.duration) < cutscene_time)
			{
				file_var_write(flog,reader.starttime);
				file_var_write(flog,reader.duration);
				Cue* killme = reader;
				if(reader == active_cues_head && reader.next != NULL)
				{
					reader.next.prev = NULL;
					active_cues_head = reader.next;
					reader = reader.next;
				}
				else if(reader == active_cues_head && reader.next == NULL)
				{
					active_cues_head = NULL;
					reader = NULL;
				}
				else if(reader.next == NULL)
				{
					reader.prev.next = NULL;
					reader = NULL;
				}
				else
				{
					reader.prev.next = reader.next;
					reader.next.prev = reader.prev;
					reader = reader.next;
				}
				
				free(killme);
			}
			else
			{
				
				if(reader.entname == NULL)
				{
					var factor = (cutscene_time - reader.starttime) / reader.duration;
					vec_lerp(camera.x,reader.startpos,reader.endpos,factor);
					vec_lerp(camera.pan,reader.startang,reader.endang,factor);
				}
				else
				{
					
					ENTITY* actor = ent_for_name(reader.entname);
					var factor = (cutscene_time - reader.starttime) / reader.duration;
					if(vec_dist(reader.startpos,reader.endpos) != 0) vec_lerp(actor.x,reader.startpos,reader.endpos,factor);
					if(vec_dist(reader.startang,reader.endang) != 0) vec_lerp(actor.pan,reader.startang,reader.endang,factor);
					if(vec_dist(reader.startscale,reader.endscale) != 0) vec_lerp(actor.scale_x,reader.startscale,reader.endscale,factor);
					if(reader.anim != NULL) ent_animate(actor,reader.anim,(factor * 100 * reader.animloops) % 100,ANM_CYCLE);
				}
				reader = reader.next;
			}
		}
		
		
		cutscene_time += time_frame;
		}
		wait(1);
		
	}
	file_close(flog);
}

function pauseScene()
{
	cutscene_paused = 1;
}

function unpauseScene()
{
	cutscene_paused = 0;
}

function freeScene()
{
	free(scene);
}

action actor()
{
	wait(1);
}



Re: need help with these structs im using [Re: The_Clyde] #327590
06/07/10 13:59
06/07/10 13:59
Joined: Dec 2005
Posts: 116
T
tD_Datura_v Offline
Member
tD_Datura_v  Offline
Member
T

Joined: Dec 2005
Posts: 116
A quick note:
It might be assumed
...that the vector() function is not roughly equivalent to the str_create function
...and that the vector() function might return a VECTOR from a shared internal pool,
...and that such memory probably should not be directly freed by the user.

VECTORs and ANGLEs might be declared in structs as such:
Code:
typdef struct t{
	ANGLE a1;
	VECTOR v1;
} t;



Of course that might be "ill-advised".




Re: need help with these structs im using [Re: tD_Datura_v] #327659
06/07/10 18:40
06/07/10 18:40
Joined: Jul 2008
Posts: 223
Pittsburgh
The_Clyde Offline OP
Member
The_Clyde  Offline OP
Member

Joined: Jul 2008
Posts: 223
Pittsburgh
That makes a good deal of sense. It there a correct way to handle vectors and angles in structs or is it better to create and address them as separate vars?

Re: need help with these structs im using [Re: The_Clyde] #327695
06/07/10 22:44
06/07/10 22:44
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline
Expert
EvilSOB  Offline
Expert

Joined: Feb 2008
Posts: 3,232
Australia
The way tD_Datura_v says is the best way, IMHO, but others may disagree.

So i would use define the structs this way
Code:
typedef struct Cue {
	STRING* entname;
	VECTOR  startpos;
	VECTOR  endpos;
	ANGLE   startang;
	ANGLE   endang;
	VECTOR  startscale;
	VECTOR  endscale;
	STRING* anim;		//animation name- or NULL
	var     animloops;
	var     starttime;
	var     duration;
	struct  Cue* next;	//used when the cue is in the linked list of active cues
	struct  Cue* prev;
} Cue; 

typedef struct Keyframe {
	var  cuetime;
	var  actions_count;
	Cue* actions[64];
} Keyframe;




"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Re: need help with these structs im using [Re: EvilSOB] #327696
06/07/10 22:54
06/07/10 22:54
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline
Expert
EvilSOB  Offline
Expert

Joined: Feb 2008
Posts: 3,232
Australia
Next, when passing custom objects as parameters or return values,
be specific wherever possible.

Code:
Cue* newCue()
{
	Cue* newcue = sys_malloc(sizeof(Cue));
	memset(newcue,0,sizeof(Cue));
	return newcue;
}

Keyframe* newKeyframe()
{
	Keyframe* newkeyframe = sys_malloc(sizeof(Keyframe));
	memset(newkeyframe,0,sizeof(Keyframe));
	return newkeyframe;
}




"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Re: need help with these structs im using [Re: EvilSOB] #327700
06/07/10 23:28
06/07/10 23:28
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline
Expert
EvilSOB  Offline
Expert

Joined: Feb 2008
Posts: 3,232
Australia
Lastly, whenever you are removing an object, be sure to remove all its sub-objects too,
before removing the object itself. That way youve still got access to them.
This is assuming of course the the sub-objects in question are NOT "shared" between objects.

Code:
function killCue(Cue* c)
{
	if(c.entname)	str_remove(c.entname);
	if(c.anim)	str_remove(c.anim);
	//note: dont free c.next and c.prev, cause they are shared
	sys_free(c);
}

function killKeyframe(Keyframe* k)
{
	var i;	for(i=0; i<64; i++)
	{
		if((k.actions)[i])
		{   killCue((k.actions)[i]);   }
	}
	sys_free(k);
}



Note :: I havent looked at loadscene or playscene yet as that would require more time than
I have to spare ATM. I'll try to take a look at work tonite...

Hope thtis has ben informative.


"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Re: need help with these structs im using [Re: EvilSOB] #327701
06/07/10 23:33
06/07/10 23:33
Joined: Jul 2008
Posts: 223
Pittsburgh
The_Clyde Offline OP
Member
The_Clyde  Offline OP
Member

Joined: Jul 2008
Posts: 223
Pittsburgh
Should I malloc the Cue array as well when I create the new Keyframe?

also- thank you very much, you've been VERY informative laugh

Last edited by The_Clyde; 06/07/10 23:34.
Re: need help with these structs im using [Re: The_Clyde] #327703
06/07/10 23:47
06/07/10 23:47
Joined: Feb 2008
Posts: 3,232
Australia
EvilSOB Offline
Expert
EvilSOB  Offline
Expert

Joined: Feb 2008
Posts: 3,232
Australia
You CAN if you want, but that will eat up memory with all the un-used Cue's.

I would suggest calling a "newCue" only when you need to (ie. you have data to put in it),
from within "loadScene" or from within your (as yet un-built) editor.


"There is no fate but what WE make." - CEO Cyberdyne Systems Corp.
A8.30.5 Commercial
Page 1 of 2 1 2

Moderated by  HeelX, Lukas, rayp, Rei_Ayanami, Superku, Tobias, TWO, VeT 

Gamestudio download | chip programmers | Zorro platform | shop | Data Protection Policy

oP group Germany GmbH | Birkenstr. 25-27 | 63549 Ronneburg / Germany | info (at) opgroup.de

Powered by UBB.threads™ PHP Forum Software 7.7.1