[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Game oriented usage of Lua?
- From: David Jeske <jeske@...>
- Date: Sun, 30 May 1999 03:10:35 -0700
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