Skip to content

CScript

ibm5155 edited this page Sep 4, 2018 · 2 revisions

By the name, C Script is a simple yet powerful way of making scripts using C/C++, it allows you to simply use the build in CScript functions to automate objects from ObjectCore and also to be easily expanded by the developer needs.

As an example of simplicity, the below function is an example of code that makes an object nonsolid:

void Hide(Object *me){
  me->Solid = false;
}

CScript interacts with any parts of the object and other parts of it by interacting with MT2D_VARS. The only limitation of CScirpt is that the input args must be const, but that will not limit your code since you can use VAR pointers so the game will edit the build in VARS from your or other Object (or anything that you desire to change), take a look in the build in function how it's done to jump a state if a given value is lower or equal:

/*
Vars:
[0] = the name of the state to be jumped
[1] <= [2], jump if true
*/
void Cscript_JumpToStateIfVarLowerEq(Object *object, MT2D_VAR **Vars) {
	int i = 0;
	int Left = Cscript_VAR_Get_Integer(object, Vars[1]);
	int Right = Cscript_VAR_Get_Integer(object, Vars[2]);
	if (Left <= Right) {
        		while (i < object->States_Count) {
			if (strcmp(object->State[i]->Name, Vars[0]->Name) == 0) {
				object->ActualState = i;
				object->ActualFrame = -1;//after this call the function is going to be increased by one so we avoid the code to miss the first state.
				object->ActualFrameWait = object->State[i]->WaitSprites[0];
				i = object->States_Count;
			}
			i++;
		}
	}
}

In this case, the VAR 0 is only used to store the name of the state to be jumped, VAR 1 could be a fixed number or a pointer to a given var inside the object, like it could be a fixed cost of a spell, VAR 2 could be a fixed number or a pointer to a given VAR inside the object, like it could point the the VAR Mana inside the Object.

Some type of functionalities may get complex to implement, but with that minimalistic model you can create from simple stuffs like a Menu system where you parse the keyboard inside the object, up to a Giant monster with AI.

Ok so, there's a limit, and the limit is that you only have four ways of function args, but don't be scared since they are quite flexible, those models are:

void ...();
void ...(Object *Caller);
void ...(Object *Caller, MT2D_VAR **Array of const Vars);
void ...(Object *Caller, Object *Obj2, MT2D_VAR **Array of const Vars);

The Array of const vars is as the name says, an array containing one or more MT2D_VARS, so you don't get limited by your arg inputs. The caller object will always be the pointer to the object that called the CSript. And of course, the Obj2 in the last option, will be the pointer for an Object where you can do stuff like, cloning it and storing this new object into the ObjectScene, making it pocible to make objects that creates other objects dynamically, like a damaged tank creating explosion objects around itself. Take a look of this example of Cscript that uses the last type of Cscript function struct:

/**
Vars[0] = Pos X
Vars[1] = Pos Y
Vars[2] = Acel X
Vars[3] = Acel Y
**/
void Cscript_CreateObject(Object *Caller, Object *NewModel, MT2D_VAR **Vars) {
	Object *NewObject;
	int X[2] = { Cscript_VAR_Get_Integer(Caller,Vars[0]),Cscript_VAR_Get_Integer(Caller,Vars[2]) };
	int Y[2] = { Cscript_VAR_Get_Integer(Caller,Vars[1]),Cscript_VAR_Get_Integer(Caller,Vars[3]) };
	NewObject = Object_Create(NewModel->Solid, NewModel->RenderOnly, NewModel->Size.X, NewModel->Size.X, X[0], Y[0], NewModel->State, NewModel->States_Count);
	NewObject->Aceleration.X = X[1];
	NewObject->Aceleration.Y = Y[1];
	if (NewModel->User_Vars_Count > 0) {
		MT2D_VAR *NewVars = (MT2D_VAR*)malloc(NewModel->User_Vars_Count * sizeof(MT2D_VAR));
		for (int i = 0; i < NewModel->User_Vars_Count; i++) {
			NewVars[i] = *MT2D_VAR_CLONE(&NewModel->User_Vars[i]);
		}

		NewObject->User_Vars = NewVars;
		NewObject->User_Vars_Count = NewModel->User_Vars_Count;
	}
	ObjectScene_Add(Caller->MyScene, NewObject);
}

This function clones a given object to a new object and stores this object into the ObjectScene from the caller object.

STDFunctions

Of course that with great power, it would be nice to have some build in functions for Cscript, and this is where STDFunctions comes into hand, well, just take a look in the function lists that were implemented:

/*AI FUNCTIONS*/
void Cscript_TeleportToCoord(Object *object, MT2D_VAR **X_Y);
void Cscript_Move(Object *object);
void Cscript_CreateObject(Object *Caller, Object *NewModel, MT2D_VAR **Vars);
void Object_GotoState_IfHit(Object *Caller, MT2D_VAR **Vars);

/*LOGIC FUNCTIONS*/
void Cscript_JumpToStateIfRandom(Object *object, MT2D_VAR **JUMPTO_CHANCE_MAX);
void Cscript_JumpToStateIfVarLowerEq(Object *object, MT2D_VAR **Vars);
void Cscript_JumpToStateIfVarHigherEq(Object *object, MT2D_VAR **Vars);

void Cscript_JumpToStateIfVarEq(Object *object, MT2D_VAR **Vars);
void Cscript_JumpNextFrameIfVarEq(Object *object, MT2D_VAR **Vars);
void Cscript_JumpNextFrameIfVarLowerEq(Object *object, MT2D_VAR **Vars);
void Cscript_JumpNextFrameIfVarHigherEq(Object *object, MT2D_VAR **Vars);
void Cscript_Object_SetState(Object *Object, MT2D_VAR **StateName);
void Cscript_Set_Var(Object *Object, MT2D_VAR **StateName);
void Cscript_RemoveObject(Object *Caller);
void Cscript_AddVar_ToObject(Object *Caller, MT2D_VAR **Vars);
/*TODO void Cscript_RemoveVar_FromObject(OBject *Caller, MT2D_VAR **Vars);*/

/*MATH FUNCTIONS*/
void Cscript_VAR_INC(Object *object, MT2D_VAR **VAR);
void Cscript_VAR_DEC(Object *object, MT2D_VAR **VAR);
void Cscript_VAR_ADD(Object *object, MT2D_VAR **VARS);
void Cscript_VAR_SUB(Object *object, MT2D_VAR **VARS);

/*AUDIO FUNCTIONS*/
void Cscript_PlaySound(Object *object,MT2D_VAR **SoundName);
void Cscript_PlayMusic(Object *object,MT2D_VAR **MusicName);

EXTRA EXAMPLES

*Check if hte shibe was hit by a bad object, if so, decreases its health bar, plays a sound and mark the object as deleted.

void TryBadHit(Object* Caller) {
	if (Caller->SpacePosition.X <= Shibe->SpacePosition.X + Shibe->Size.X) {
		if (Caller->SpacePosition.X + Caller->Size.X >= Shibe->SpacePosition.X) {
			if (Caller->SpacePosition.Y <= Shibe->SpacePosition.Y + Shibe->Size.Y) {
				if (Caller->SpacePosition.Y + Caller->Size.Y >= Shibe->SpacePosition.Y) {
					MT2D_VAR ** x = MT2D_VAR_Create_Matrix1(Pointer_Health);
					Cscript_VAR_DEC(Shibe, x);
					free(x);
					MT2D_Play_Audio("hit.wav");
					Caller->CanDelete = true;
				}
			}
		}
	}
}
  • A menu system that checks the keyboard and what's the next selected item
void TryMove(Object *Caller) {
	int Key = 0;
	if (MT2D_Keyboard_touched()) {
		Key = MT2D_Keyboard_keytouched();
		if (Key == arrow_key_pressed) {
			Key = MT2D_Keyboard_keytouched();
			if (Key == arrow_up_pressed) {
				Selected = (Selected == 0 ? 2 : Selected - 1);
				Caller->SpacePosition.Y = 90 + 30 * Selected;
			}
			else if (Key == arrow_down_pressed) {
				Selected = (Selected == 2 ? 0 : Selected + 1);
				Caller->SpacePosition.Y = 90 + 30 * Selected;
			}
		}
		else if (Key == enter_pressed || Key == ' ') {
			Enter_pressed = true;
		}
	}
}

*Check if the player spaceship can shoot, main game loop informs into User_Vars[1] if a shoot was requested while User_Vars[0] stores the timeout for the next shoot, plus it creates a new projectile with fixed speed and initial position.

void TryFire(Object *Caller) {
	MT2D_VAR **Tmp;
	if (*(int*)Caller->User_Vars[0].Data > 0) {
		*(int*)Caller->User_Vars[0].Data = *(int*)Caller->User_Vars[0].Data - 1;
	}
	if (*(int*)Caller->User_Vars[1].Data == 1) {
		if (*(int*)Caller->User_Vars[0].Data == 0) {
			MT2D_VAR *NewPosX = MT2D_Object_Create_Var_Int("NewX", Caller->SpacePosition.X + Caller->Size.X + 3);
			Tmp = MT2D_VAR_Create_Matrix4(NewPosX, Pointer_PosY, Const10, Const0);
			Cscript_CreateObject(Caller, Projectile1, Tmp);
			MT2D_Play_Audio("Projectiles/Proj.ogg");
			free(Tmp);
			*(int*)Caller->User_Vars[0].Data = 5;
		}
	}
}

More examples can be found at ObjectCore

Clone this wiki locally