Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
16 KB
Referenced Files
None
Subscribers
None
diff --git a/src/GameObjects.h b/src/GameObjects.h
index 2976b34..51370e0 100644
--- a/src/GameObjects.h
+++ b/src/GameObjects.h
@@ -1,152 +1,153 @@
/*
* Copyright (C) 2011-2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GAME_OBJECTS_H
#define GAME_OBJECTS_H
#include "Globals.h"
+#include "ScriptUserData.h"
#include <SDL/SDL.h>
#include <string>
#include <vector>
#include <utility>
#include <map>
class Game;
class Player;
//The different gameObject events.
enum GameObjectEventType{
//Event called when the player walks on the gameObject.
GameObjectEvent_PlayerWalkOn=1,
//Event called when the player is on the gameObject.
GameObjectEvent_PlayerIsOn,
//Event called when the player leaves the gameObject.
//Currently unimplemented.
GameObjectEvent_PlayerLeave,
//Event called when the player toggles it. (DOWN key)
GameObjectEvent_OnToggle=0x10000,
//Event called when the player switches it on. (DOWN key)
GameObjectEvent_OnSwitchOn=0x10001,
//Event called when the player switches it off. (DOWN key)
GameObjectEvent_OnSwitchOff=0x10002,
};
//The different gameObject properties.
enum GameObjectPropertyType{
//If the player can walk on the gameObject.
GameObjectProperty_PlayerCanWalkOn=1,
//If the object is spiked.
GameObjectProperty_IsSpikes,
//If the gameObject has some flags.
GameObjectProperty_Flags,
};
//The different box types that can be requested using the getBox(int boxType) method.
enum GameObjectBoxType{
//Box of the current position.
BoxType_Current=0,
//Box of the base/start position.
BoxType_Base,
//Box of the previous position.
BoxType_Previous,
//The movement of the block since last position.
BoxType_Delta,
//The velocity for when the player is standing on it.
BoxType_Velocity,
};
//The GameObject class.
-class GameObject{
+class GameObject:public ScriptUserClass<'B','L','O','K',GameObject>{
protected:
//The box of the gameObject.
//It's used for the location of the gameObject and the size.
SDL_Rect box;
public:
//The type of the GameObject.
int type;
//Pointer to the Game state.
Game* parent;
//Constructor.
//parent: Pointer to the Game state.
GameObject(Game* parent);
//Destructor.
~GameObject();
//Method used to retrieve a certain box from the GameObject.
//boxType: The type of box that is requested. (default=0)
//Returns: An SDL_Rect.
virtual SDL_Rect getBox(int boxType=0);
//This method is used to place the location on a given location.
//x: The x location to place the gameObject.
//y: The y location to place the gameObject.
virtual void setLocation(int x,int y);
//This method is used to set the base of an object to a given location.
//x: The x location to place the gameObject.
//y: The y location to place the gameObject.
virtual void setBaseLocation(int x,int y);
//Method used to draw the GameObject.
virtual void show()=0;
//Save the state of the GameObject, used for moving blocks, etc.
virtual void saveState();
//Load the state of the GameObject, used for moving blocks, etc.
virtual void loadState();
//Reset the state of the GameObject, used for moving blocks, etc.
//save: Boolean if the saved state should also be reset.
virtual void reset(bool save);
//Play an animation.
//flags: TODO???
virtual void playAnimation(int flags);
//Invoke an event of the GameObject.
//eventType: The event type.
virtual void onEvent(int eventType);
//Method used to request certain properties of the GameObject.
//propertyType: The property that is requested.
//obj: Pointer to the player.
virtual int queryProperties(int propertyType,Player* obj);
//Method used to retrieve the additional editor data for the GameObject.
//Used for messages, moving positions, etc...
//obj: Vector containing the editorData pairs. (key, value)
virtual void getEditorData(std::vector<std::pair<std::string,std::string> >& obj);
//Set the editorData.
//obj: Map containing the key/value for the editor data.
virtual void setEditorData(std::map<std::string,std::string>& obj);
//Get a single property of the block.
//property: The property to return.
//Returns: The value for the requested property.
virtual std::string getEditorProperty(std::string property);
//Set a single property of the block.
//property: The property to set.
//value: The new value for the property.
virtual void setEditorProperty(std::string property,std::string value);
//Update method for GameObjects, used for moving blocks.
virtual void move();
};
//We include block.h here because it needs some things defined above.
#include "Block.h"
#endif
diff --git a/src/ScriptAPI.h b/src/ScriptAPI.h
index d7fc7d4..025945a 100644
--- a/src/ScriptAPI.h
+++ b/src/ScriptAPI.h
@@ -1,189 +1,190 @@
/*
* Copyright (C) 2012 Me and My Shadow
*
* This file is part of Me and My Shadow.
*
* Me and My Shadow is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Me and My Shadow is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
*/
int test(lua_State* state){
cout<<"Hello world"<<endl;
return 0;
}
///////////////////////////BLOCK SPECIFIC///////////////////////////
int getBlockById(lua_State* state){
//Get the number of args, this MUST be one.
int args=lua_gettop(state);
if(args!=1){
lua_pushstring(state,_("Incorrect number of arguments for getBlockById, expected 1."));
lua_error(state);
}
//Make sure the given argument is an id (string).
if(!lua_isstring(state,1)){
lua_pushstring(state,_("Invalid type for argument 1 of getBlockById."));
lua_error(state);
}
+ //Check if the currentState is the game state.
+ Game* game=dynamic_cast<Game*>(currentState);
+ if(game==NULL) return 0;
+
//Get the actual game object.
string id=lua_tostring(state,1);
- //FIXME: We can't just assume that the currentState is the game state.
- std::vector<GameObject*> levelObjects=(dynamic_cast<Game*>(currentState))->levelObjects;
+ std::vector<GameObject*>& levelObjects=game->levelObjects;
GameObject* object=NULL;
for(int i=0;i<levelObjects.size();i++){
if(levelObjects[i]->getEditorProperty("id")==id){
object=levelObjects[i];
break;
}
}
if(object==NULL){
//Unable to find the requested object.
//Return nothing, will result in a nil in the script.
return 0;
}
//Create the userdatum.
- GameObject** datum = (GameObject**)lua_newuserdata(state,sizeof(GameObject*));
- *datum=object;
- //And set the metatable for the userdatum.
- luaL_getmetatable(state,"block");
- lua_setmetatable(state,-2);
+ object->createUserData(state,"block");
//We return one object, the userdatum.
return 1;
}
int getBlocksById(lua_State* state){
//Get the number of args, this MUST be one.
int args=lua_gettop(state);
if(args!=1){
lua_pushstring(state,_("Incorrect number of arguments for getBlocksById, expected 1."));
lua_error(state);
}
//Make sure the given argument is an id (string).
if(!lua_isstring(state,1)){
lua_pushstring(state,_("Invalid type for argument 1 of getBlocksById."));
lua_error(state);
}
+ //Check if the currentState is the game state.
+ Game* game=dynamic_cast<Game*>(currentState);
+ if(game==NULL) return 0;
+
//Get the actual game object.
string id=lua_tostring(state,1);
- //FIXME: We can't just assume that the currentState is the game state.
- std::vector<GameObject*> levelObjects=(dynamic_cast<Game*>(currentState))->levelObjects;
+ std::vector<GameObject*>& levelObjects=game->levelObjects;
std::vector<GameObject*> result;
for(int i=0;i<levelObjects.size();i++){
if(levelObjects[i]->getEditorProperty("id")==id){
result.push_back(levelObjects[i]);
}
}
//Create the table that will hold the result.
lua_createtable(state,result.size(),0);
//Loop through the results.
for(int i=0;i<result.size();i++){
//Create the userdatum.
- GameObject** datum = (GameObject**)lua_newuserdata(state,sizeof(GameObject*));
- *datum=result[i];
- //And set the metatable for the userdatum.
- luaL_getmetatable(state,"block");
- lua_setmetatable(state,-2);
+ result[i]->createUserData(state,"block");
//And set the table.
lua_rawseti(state,-2,i+1);
}
//We return one object, the userdatum.
return 1;
}
int getBlockLocation(lua_State* state){
//Make sure there's only one argument and that argument is an userdatum.
int args=lua_gettop(state);
if(args!=1){
lua_pushstring(state,_("Incorrect number of arguments for getBlockLocation, expected 1."));
lua_error(state);
}
if(!lua_isuserdata(state,1)){
lua_pushstring(state,_("Invalid type for argument 1 of getBlockLocation."));
lua_error(state);
}
- GameObject* object = *(GameObject**)lua_touserdata(state,1);
+ GameObject* object = GameObject::getObjectFromUserData(state,1);
+ if(object==NULL) return 0;
//Get the object.
lua_pushnumber(state,object->getBox().x);
lua_pushnumber(state,object->getBox().y);
return 2;
}
int setBlockLocation(lua_State* state){
//Check the number of arguments.
int args=lua_gettop(state);
//Make sure the number of arguments is correct.
if(args!=3){
lua_pushstring(state,_("Incorrect number of arguments for setBlockLocation, expected 3."));
lua_error(state);
}
//Check if the arguments are of the right type.
if(!lua_isuserdata(state,1)){
lua_pushstring(state,_("Invalid type for argument 1 of getBlockLocation."));
lua_error(state);
}
if(!lua_isnumber(state,2)){
lua_pushstring(state,_("Invalid type for argument 2 of getBlockLocation."));
lua_error(state);
}
if(!lua_isnumber(state,3)){
lua_pushstring(state,_("Invalid type for argument 3 of getBlockLocation."));
lua_error(state);
}
//Now get the pointer to the object.
- //TODO: Make sure the object sill exists.
- GameObject* object = *(GameObject**)lua_touserdata(state,1);
+ GameObject* object = GameObject::getObjectFromUserData(state,1);
+ if(object==NULL) return 0;
int x=lua_tonumber(state,2);
int y=lua_tonumber(state,3);
object->setLocation(x,y);
return 0;
}
//Array with the methods for the block library.
static const struct luaL_Reg blocklib_m[]={
{"getBlockById",getBlockById},
{"getBlocksById",getBlocksById},
{"getLocation",getBlockLocation},
{"setLocation",setBlockLocation},
{NULL,NULL}
};
int luaopen_block(lua_State* state){
luaL_newlib(state,blocklib_m);
//Create the metatable for the block userdata.
luaL_newmetatable(state,"block");
lua_pushstring(state,"__index");
lua_pushvalue(state,-2);
lua_settable(state,-3);
+ GameObject::registerMetatableFunctions(state,-3);
+
//Register the functions and methods.
luaL_setfuncs(state,blocklib_m,0);
return 1;
}
//Register the libraries.
void registerFunctions(ScriptExecutor* executor){
//
}
diff --git a/src/ScriptUserData.h b/src/ScriptUserData.h
new file mode 100644
index 0000000..facf456
--- /dev/null
+++ b/src/ScriptUserData.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2012 Me and My Shadow
+ *
+ * This file is part of Me and My Shadow.
+ *
+ * Me and My Shadow is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Me and My Shadow is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Me and My Shadow. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SCRIPTUSERDATA_H
+#define SCRIPTUSERDATA_H
+
+extern "C" {
+#include "lua.h"
+#include "lualib.h"
+#include "lauxlib.h"
+}
+#include <string>
+
+#ifdef _DEBUG
+#include <assert.h>
+#include <stdio.h>
+#endif
+
+/** A struct represents the Lua user data.
+*/
+struct ScriptUserData{
+ char sig1,sig2,sig3,sig4;
+ void* data;
+ ScriptUserData* prev;
+ ScriptUserData* next;
+};
+
+/** A helper class to bind C++ class to Lua user data.
+*/
+
+template<char sig1,char sig2,char sig3,char sig4,class T>
+class ScriptUserClass{
+public:
+ ScriptUserClass():scriptUserDataHead(NULL){
+ }
+
+ /** Create a Lua user data pointed to this object. (-0,+1,e)
+ \param state Lua state.
+ \param metatableName Metatable name.
+ */
+ void createUserData(lua_State *state,const char* metatableName){
+ //Convert this object to T.
+ T* obj=dynamic_cast<T*>(this);
+#ifdef _DEBUG
+ //It should not be NULL unless there is a bug in code
+ assert(obj!=NULL);
+#endif
+
+ //Create user data.
+ ScriptUserData* ud=(ScriptUserData*)lua_newuserdata(state,sizeof(ScriptUserData));
+
+ ud->sig1=sig1;
+ ud->sig2=sig2;
+ ud->sig3=sig3;
+ ud->sig4=sig4;
+ ud->data=obj;
+
+ //Add it to the linked list.
+ ud->next=scriptUserDataHead;
+ ud->prev=NULL;
+ if(scriptUserDataHead) scriptUserDataHead->prev=ud;
+ scriptUserDataHead=ud;
+
+ //Set matatable and we are done.
+ luaL_getmetatable(state,metatableName);
+ lua_setmetatable(state,-2);
+
+#ifdef _DEBUG
+ printf("ScriptUserClass '%c%c%c%c' (%p) created userdata: %p\n",
+ sig1,sig2,sig3,sig4,this,ud);
+#endif
+ }
+
+ /** Destroys all Lua user data associated to this object.
+ */
+ void destroyUserData(){
+ while(scriptUserDataHead){
+#ifdef _DEBUG
+ printf("ScriptUserClass '%c%c%c%c' (%p) invalidated userdata: %p\n",
+ sig1,sig2,sig3,sig4,this,scriptUserDataHead);
+#endif
+ scriptUserDataHead->data=NULL;
+ scriptUserDataHead=scriptUserDataHead->next;
+ }
+ }
+
+ /** Convert a Lua user data in Lua stack to object. (-0,+0,e)
+ \param state Lua state.
+ \param idx Index.
+ \return The object. NULL if this user data is invalid.
+ \note This data should be a user data.
+ */
+ static T* getObjectFromUserData(lua_State *state,int idx){
+ ScriptUserData* ud=(ScriptUserData*)lua_touserdata(state,idx);
+
+ if(ud && ud->sig1==sig1 && ud->sig2==sig2 && ud->sig3==sig3 && ud->sig4==sig4)
+ return reinterpret_cast<T*>(ud->data);
+ return NULL;
+ }
+
+ /** Register __gc, (__eq TODO) to given table. (-0,+0,e)
+ \param state Lua state.
+ \param idx Index.
+ */
+ static void registerMetatableFunctions(lua_State *state,int idx){
+ lua_pushstring(state,"__gc");
+ lua_pushcfunction(state,&garbageCollectorFunction);
+ lua_rawset(state,idx);
+ }
+
+ virtual ~ScriptUserClass(){
+ destroyUserData();
+ }
+private:
+ ScriptUserData* scriptUserDataHead;
+
+ /** The garbage collector (__gc) function.
+ */
+ static int garbageCollectorFunction(lua_State *state){
+ //Check if it's a user data. It can be a table (the library itself)
+ if(!lua_isuserdata(state,1)) return 0;
+
+ ScriptUserData* ud=(ScriptUserData*)lua_touserdata(state,1);
+
+ if(ud){
+ if(ud->data){
+#ifdef _DEBUG
+ //It should be impossible unless there is a bug in code
+ assert(ud->sig1==sig1 && ud->sig2==sig2 && ud->sig3==sig3 && ud->sig4==sig4);
+#endif
+ //Unlink it
+ if(ud->next) ud->next->prev=ud->prev;
+ if(ud->prev) ud->prev->next=ud->next;
+ else{
+ ScriptUserClass* owner=static_cast<ScriptUserClass*>(reinterpret_cast<T*>(ud->data));
+ owner->scriptUserDataHead=ud->next;
+ }
+#ifdef _DEBUG
+ printf("ScriptUserClass '%c%c%c%c' (%p) unlinked userdata: %p\n",
+ sig1,sig2,sig3,sig4,
+ static_cast<ScriptUserClass*>(reinterpret_cast<T*>(ud->data)),ud);
+#endif
+ }
+
+ ud->data=NULL;
+ ud->next=NULL;
+ ud->prev=NULL;
+ }
+
+ return 0;
+ }
+};
+
+#endif

File Metadata

Mime Type
text/x-diff
Expires
Sat, May 16, 8:21 PM (1 d, 16 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
63517
Default Alt Text
(16 KB)

Event Timeline