lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I've included some Lua code snippits at the bottom.

On Fri, May 28, 1999 at 04:17:53AM -0300, Vincent PENQUERC'H wrote:
>> I hope people don't mind that this was so specific... I realize
>> that many people on this list are not interested in adventure game
>> engine internals and certainly haven't played Grim Fandango.  But
>> I'd like to hear how other people have used Lua as well!
> 
> I'm new to Lua, and thus I may not have taken the best path, but
> here is the way I used it: I have several 'entities' in my game,
> most of them are items or characters. Each of them, when created,
> creates a Lua table representing it.
>
> This table is composed of data and function fields. The only data
> field known to C++ is set at the object construction, and is the
> 'owner' field, initialized to the C++ pointer to the object (a Lua
> userdata). All other data fields are left to the use of Lua scipts.

That sounds similar to how my stuff works...

> The functions depend on the type of table. For a character, for
> example, several functions are predefined and have special meaning
> for the C++ game engine: 'onthink', 'ontalk', 'onhit', 'ondeath',
> etc... Whenever something happens which correspdonds to one of
> those, the function is called (if defined).  This way, default
> behavior is executed if the function is not defined in the table,
> and it can be overriden by defining the function.

Hmm... the methods are all the same for all "Sprites" in my game, and
the Lua code just does different things for different types of
objects.

My methods are "ai_event", "do_tick" (for doing object Physics), and
inputEvent (if an object is active).

> This set of predefined Lua table functions have at hand a set of
> registered C functions that access everything's necessary
> (examples include CharFindPathTo, CharFindPathAround, CharAttack,
> CharSay, CharStopMoving, CharGetInventory, etc...). some of these
> basic bricks are very low level (CharGetXPos) 

Sounds very similar to my stuff as well. I have C_obj_goto,
C_obj_viewfollow, C_obj_delete, C_obj_getvelocity, C_obj_setvelocity.


---------------------------------------------------------------

I also have a multiple inheritence scheme I used to construct objects
out of smaller components I call traits. (The 'traits' term is
borrowed from the Sun SELF language) For example, below is my
helicopter object, notice the traits listed in the _parents line and
the VisualRep pointing to the VisualRep table. The way I handle
defining Visual Representation is worth an email in itself, so if you
are interested after what you see below, go check out this URL:

http://www.chat.net/~jeske/Projects/HZ/docs/sprite_definition.html


hz_register_objtype("heli", {
	_parents = { air_physics, controllable, collidable },
	imgdir = 2.0, -- image index
	rimgdir = 1.0, -- rotor image index
	direction = 0.0, 
	bullet_type = "bullet",
	objtype = "heli",
	exp_timer = 0.0,
	frame_time = 70,
	layer = 1,
	VisualRep = VisualReps.Heli,

	-- dummy ai_event
	ai_event = function(self)
	end,

	new = function (self,a_list) -- constructor
		if (type(a_list) ~= 'table') then
			print("heli:new() called with non-table "..tostring(a_list));
		else
			a_list._parents = { self };
			a_list.key = {}; -- make our private keydown list
			a_list.ctrl_centered = 1.0;
			a_list.dest_dir = 0.0;
		end
		return (a_list);
	end
}); -- register done

--------------------------------------------------------------

Here is a very simple trait... "collidable". This is just responsible
for creating explosions:

collisions_active = 0;
MAX_COLLISIONS = 5;

collidable = {
ge_collision = function(self,x,y,whoIhit)
	if ((collisions_active < MAX_COLLISIONS) and (self.layer == whoIhit.layer)) then
		C_addsprite("explosion",x,y);
		collisions_active = collisions_active + 1;
	end
end

}; -- end collidable

--------------------------------------------------------------

This last example is a bit long, but here you can see one of the
physics traits... air_physics. It includes all the physics
calculations for flying objects:

air_physics = {
vx = 0, vy = 0, rot = 0,
doTick = function(self,tick_diff)
	local vx, vy, rot;
	local dest_dir = self.dest_dir;
	local ax, ay; -- acceleration vectors


	local exp_timer = self.exp_timer;
	local frame_time = self.frame_time; -- 70 seconds? frames? what is this?
	local exp_img_num = self.rimgdir;
	local EXP_IMG_COUNT = 10;

	exp_timer = exp_timer + tick_diff;

	while (exp_timer > frame_time) do
		exp_timer = exp_timer - frame_time;
		exp_img_num = exp_img_num + 1;

		if (exp_img_num > EXP_IMG_COUNT) then
			exp_img_num = 1;
		end
	end

	self.exp_timer = exp_timer;
	self.rimgdir = floor(exp_img_num);

	vx, vy = C_obj_getVelocity(self.objnum);
	rot = self.rot;

	if (self.ctrl_centered == 1.0) then
		ax = 0.0;
		ay = 0.0;
	else -- (not self.ctrl_centered)
		-- accelerate in that direction!
		ax = Dirx[floor(dest_dir)];
		ay = Diry[floor(dest_dir)];
		print(format("accelerate at (%f,%f)",ax,ay));
	end
	
	if (ax == 0.0) then	
		-- coast!
		if (vx > tick_diff/2000.0) then
			vx = vx - tick_diff/2000.0;
		elseif (vx < -tick_diff/2000.0) then
			vx = vx + tick_diff/2000.0;
		else
			vx = 0;
		end
	else
		-- apply the acceleration!
		vx = vx + (ax * tick_diff/4000.0);
	end

	if (ay == 0.0) then
		-- coast!
		if (vy > tick_diff/2000.0) then
			vy = vy - tick_diff/2000.0;
		elseif (vy < -tick_diff/2000.0) then
			vy = vy + tick_diff/2000.0;
		else
			vy = 0;
		end	
	else
		-- apply the acceleration!
		vy = vy + (ay * tick_diff/4000.0);
	end

	if (self.ctrl_centered == 1.0) then
		C_obj_setVelocity(self.objnum,vx,vy);
		return;
	end

	local i_rot = floor(rot);

	if (i_rot == dest_dir) then
		-- we're facing, so given an acceleration boost!
		vx = vx + (ax * tick_diff/2000.0);
		vy = vy + (ay * tick_diff/2000.0);
	else
		-- we need to turn "into the wind"
		local turn_vec;
		local cw_distance;
		local ccw_distance;
		local MAX_SHIP_FRAME = 40;

		-- first, figur out what direction to turn
		if (i_rot > dest_dir) then
			ccw_distance = i_rot - dest_dir;
			cw_distance  = MAX_SHIP_FRAME - (ccw_distance);
		else
			cw_distance = dest_dir - i_rot;
			ccw_distance = MAX_SHIP_FRAME - (cw_distance);
		end

		local TURN_RATE = 1.0;

		if (cw_distance < ccw_distance) then
			if (cw_distance < TURN_RATE) then
				turn_vec = cw_distance;
			else
				turn_vec = TURN_RATE; -- cw
			end
		else
			if (ccw_distance < TURN_RATE) then
				turn_vec = 0.0 - cw_distance;
			else
				turn_vec = 0.0 - TURN_RATE; -- ccw
			end
		end

		i_rot = i_rot + turn_vec;
		if (i_rot < 0.0) then
			i_rot = i_rot + MAX_SHIP_FRAME;
		end
		if (i_rot >= MAX_SHIP_FRAME) then
			i_rot = i_rot - MAX_SHIP_FRAME;
		end
	end 
	self.imgdir = i_rot + 1;
	self.rot = i_rot;
	C_obj_setVelocity(self.objnum,vx,vy);

end -- function end

}; -- end air_physics

-- 
David Jeske (N9LCA) + http://www.chat.net/~jeske/ + jeske@chat.net