Skip to content
Snippets Groups Projects
Commit c38e75c4 authored by dg's avatar dg
Browse files

Added Entity:setMoveAnim(oldx, oldy, speed) method to make entities move...

Added Entity:setMoveAnim(oldx, oldy, speed) method to make entities move around the map with smooth movements. This is not used by default, modules can choose to use it or not


git-svn-id: http://svn.net-core.org/repos/t-engine4@2204 51575b47-30f0-44d4-a5cc-537603b46e54
parent 0aa74896
No related branches found
No related tags found
No related merge requests found
......@@ -135,6 +135,8 @@ function _M:move(x, y, force)
e.x = x
e.y = y
map.particles[e] = true
-- Give it our main _mo for display coords
e._mo = self._mo
end
end
for i = 1, #del do self.__particles[del[i]] = nil end
......
......@@ -224,6 +224,21 @@ function _M:getMapObjects(tiles, mos, z)
until not mo
end
--- Setup movement animation for the entity
-- The entity is supposed to posses a correctly set x and y pair of fields - set to the current (new) position
function _M:setMoveAnim(oldx, oldy, speed)
if not self._mo then return end
self._mo:setMoveAnim(oldx, oldy, self.x, self.y, speed)
if not self.add_displays then return end
for i = 1, #self.add_displays do
if self.add_displays[i]._mo then
self.add_displays[i]._mo:setMoveAnim(oldx, oldy, self.x, self.y, speed)
end
end
end
--- Get the entity image as an sdl surface and texture for the given tiles and size
-- @param tiles a Tiles instance that will handle the tiles (usualy pass it the current Map.tiles)
-- @param w the width
......
......@@ -506,12 +506,13 @@ function _M:display(x, y, nb_keyframe)
local ox, oy = self.display_x, self.display_y
self.display_x, self.display_y = x or self.display_x, y or self.display_y
self._map:toScreen(self.display_x, self.display_y)
self._map:toScreen(self.display_x, self.display_y, nb_keyframe)
-- Tactical display
if self.view_faction then
local e
local z
local adx, ady
local friend
for i = self.mx, self.mx + self.viewport.mwidth - 1 do
for j = self.my, self.my + self.viewport.mheight - 1 do
......@@ -524,12 +525,13 @@ function _M:display(x, y, nb_keyframe)
if e.faction then
if not self.actor_player then friend = Faction:factionReaction(self.view_faction, e.faction)
else friend = self.actor_player:reactionToward(e) end
if e._mo then adx, ady = e._mo:getMoveAnim(i, j) else adx, ady = 0, 0 end -- Make sure we display on the real screen coords: handle current move anim position
if friend > 0 then
self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_friend):toScreen(self.display_x + (i - self.mx) * self.tile_w * self.zoom, self.display_y + (j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_friend):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
elseif friend < 0 then
self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_enemy):toScreen(self.display_x + (i - self.mx) * self.tile_w * self.zoom, self.display_y + (j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_enemy):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
else
self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_neutral):toScreen(self.display_x + (i - self.mx) * self.tile_w * self.zoom, self.display_y + (j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
self.tilesTactic:get(nil, 0,0,0, 0,0,0, self.faction_neutral):toScreen(self.display_x + (adx + i - self.mx) * self.tile_w * self.zoom, self.display_y + (ady + j - self.my) * self.tile_h * self.zoom, self.tile_w * self.zoom, self.tile_h * self.zoom)
end
end
end
......@@ -957,13 +959,16 @@ end
--- Display the particle emiters, called by self:display()
function _M:displayParticles(nb_keyframes)
nb_keyframes = nb_keyframes or 1
local adx, ady
local del = {}
local e = next(self.particles)
while e do
if e._mo then adx, ady = e._mo:getMoveAnim(e.x, e.y) else adx, ady = 0, 0 end -- Make sure we display on the real screen coords: handle current move anim position
if nb_keyframes == 0 and e.x and e.y then
-- Just display it, not updating, no emiting
if e.x + e.radius >= self.mx and e.x - e.radius < self.mx + self.viewport.mwidth and e.y + e.radius >= self.my and e.y - e.radius < self.my + self.viewport.mheight then
alive = e.ps:toScreen(self.display_x + (e.x - self.mx + 0.5) * self.tile_w * self.zoom, self.display_y + (e.y - self.my + 0.5) * self.tile_h * self.zoom, self.seens(e.x, e.y), e.zoom * self.zoom)
alive = e.ps:toScreen(self.display_x + (adx + e.x - self.mx + 0.5) * self.tile_w * self.zoom, self.display_y + (ady + e.y - self.my + 0.5) * self.tile_h * self.zoom, self.seens(e.x, e.y), e.zoom * self.zoom)
end
elseif e.x and e.y then
-- Update more, if needed
......@@ -972,7 +977,7 @@ function _M:displayParticles(nb_keyframes)
-- Only draw the first keyframe
if i == 1 and alive and e.x + e.radius >= self.mx and e.x - e.radius < self.mx + self.viewport.mwidth and e.y + e.radius >= self.my and e.y - e.radius < self.my + self.viewport.mheight then
alive = e.ps:toScreen(self.display_x + (e.x - self.mx + 0.5) * self.tile_w * self.zoom, self.display_y + (e.y - self.my + 0.5) * self.tile_h * self.zoom, self.seens(e.x, e.y), e.zoom * self.zoom, nb_keyframes)
alive = e.ps:toScreen(self.display_x + (adx + e.x - self.mx + 0.5) * self.tile_w * self.zoom, self.display_y + (ady + e.y - self.my + 0.5) * self.tile_h * self.zoom, self.seens(e.x, e.y), e.zoom * self.zoom, nb_keyframes)
end
-- Update the particles enough times
e.ps:update()
......
......@@ -58,7 +58,7 @@ function _M:removeParticles(ps)
end
end
--- Moves an actor on the map
--- Moves a projectile on the map
-- *WARNING*: changing x and y properties manualy is *WRONG* and will blow up in your face. Use this method. Always.
-- @param map the map to move onto
-- @param x coord of the destination
......@@ -102,6 +102,8 @@ function _M:move(x, y, force)
e.x = x
e.y = y
map.particles[e] = true
-- Give it our main _mo for display coords
e._mo = self._mo
end
end
for i = 1, #del do self.__particles[del[i] ] = nil end
......
......@@ -25,6 +25,8 @@ local DamageType = require "engine.DamageType"
--- Handles actors projecting damage to zones/targets
module(..., package.seeall, class.make)
_M.projectile_class = "engine.Projectile"
function _M:init(t)
end
......@@ -165,8 +167,6 @@ function _M:canProject(t, x, y)
return false, lx, ly, radius_x, radius_y
end
_M.projectile_class = "engine.Projectile"
--- Project damage to a distance using a moving projectile
-- @param t a type table describing the attack, passed to engine.Target:getType() for interpretation
-- @param x target coords
......
......@@ -340,6 +340,7 @@ end
function _M:move(x, y, force)
local moved = false
local ox, oy = self.x, self.y
if force or self:enoughEnergy() then
-- Confused ?
......@@ -388,6 +389,10 @@ function _M:move(x, y, force)
DamageType:get(DamageType.FIREBURN).projector(p.src, self.x, self.y, DamageType.FIREBURN, p.dam)
end
if moved and not force and ox and oy and (ox ~= self.x or oy ~= self.y) then
self:setMoveAnim(ox, oy, 3)
end
return moved
end
......
......@@ -249,6 +249,7 @@ function _M:loaded()
engine.GameTurnBased.loaded(self)
engine.interface.GameMusic.loaded(self)
engine.interface.GameSound.loaded(self)
Actor.projectile_class = "mod.class.Projectile"
Zone:setup{
npc_class="mod.class.NPC", grid_class="mod.class.Grid", object_class="mod.class.Object", trap_class="mod.class.Trap",
on_setup = function(zone)
......
-- ToME - Tales of Maj'Eyal
-- Copyright (C) 2009, 2010 Nicolas Casalini
--
-- This program 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.
--
-- This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
require "engine.Projectile"
module(..., package.seeall, class.inherit(engine.Projectile))
function _M:init(t, no_default)
engine.Projectile.init(self, t, no_default)
end
--- Moves a projectile on the map
-- We override it to allow for movement animations
function _M:move(x, y, force)
local ox, oy = self.x, self.y
local moved = engine.Projectile.move(self, x, y, force)
if moved and not force and ox and oy and (ox ~= self.x or oy ~= self.y) then
self:setMoveAnim(ox, oy, 3)
end
return moved
end
......@@ -57,6 +57,8 @@ static int map_object_new(lua_State *L)
obj->on_remember = lua_toboolean(L, 4);
obj->on_unknown = lua_toboolean(L, 5);
obj->move_max = 0;
obj->valid = TRUE;
obj->dx = luaL_checknumber(L, 6);
obj->dy = luaL_checknumber(L, 7);
......@@ -153,6 +155,51 @@ static int map_object_invalid(lua_State *L)
return 0;
}
static int map_object_set_move_anim(lua_State *L)
{
map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
// If at rest use satrting point
if (!obj->move_max)
{
obj->oldx = luaL_checknumber(L, 2);
obj->oldy = luaL_checknumber(L, 3);
}
// If already moving, compute starting point
else
{
float nx = luaL_checknumber(L, 4);
float ny = luaL_checknumber(L, 5);
float adx = nx - obj->oldx;
float ady = ny - obj->oldy;
obj->oldx = adx * obj->move_step / (float)obj->move_max + obj->oldx;
obj->oldy = ady * obj->move_step / (float)obj->move_max + obj->oldy;
}
obj->move_step = 0;
obj->move_max = luaL_checknumber(L, 6);
return 0;
}
static int map_object_get_move_anim(lua_State *L)
{
map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
int i = luaL_checknumber(L, 2);
int j = luaL_checknumber(L, 3);
if (!obj->move_max)
{
lua_pushnumber(L, 0);
lua_pushnumber(L, 0);
}
else
{
float adx = (float)i - obj->oldx;
float ady = (float)j - obj->oldy;
lua_pushnumber(L, (adx * obj->move_step / (float)obj->move_max - adx));
lua_pushnumber(L, (ady * obj->move_step / (float)obj->move_max - ady));
}
return 2;
}
static int map_object_is_valid(lua_State *L)
{
map_object *obj = (map_object*)auxiliar_checkclass(L, "core{mapobj}", 1);
......@@ -595,8 +642,8 @@ static int map_set_scroll(lua_State *L)
}
inline void display_map_quad(map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, bool obscure) ALWAYS_INLINE;
void display_map_quad(map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, bool obscure)
inline void display_map_quad(map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, bool obscure, int nb_keyframes) ALWAYS_INLINE;
void display_map_quad(map_type *map, int dx, int dy, float dz, map_object *m, int i, int j, float a, bool obscure, int nb_keyframes)
{
float r, g, b;
if (!obscure)
......@@ -622,6 +669,22 @@ void display_map_quad(map_type *map, int dx, int dy, float dz, map_object *m, in
}
}
// Handle move anim
float animdx = 0, animdy = 0;
if (m->move_max)
{
m->move_step += nb_keyframes;
if (m->move_step >= m->move_max) m->move_max = 0; // Reset once in place
if (m->move_max)
{
float adx = (float)i - m->oldx;
float ady = (float)j - m->oldy;
animdx = map->tile_w * (adx * m->move_step / (float)m->move_max - adx);
animdy = map->tile_h * (ady * m->move_step / (float)m->move_max - ady);
}
}
tglColor4f(r, g, b, (a > 1) ? 1 : ((a < 0) ? 0 : a));
int z;
......@@ -631,7 +694,7 @@ void display_map_quad(map_type *map, int dx, int dy, float dz, map_object *m, in
if (multitexture_active && shaders_active) tglActiveTexture(GL_TEXTURE0+z);
glBindTexture(m->textures_is3d[z] ? GL_TEXTURE_3D : GL_TEXTURE_2D, m->textures[z]);
}
DO_QUAD(dx + m->dx, dy + m->dy, z, m->scale);
DO_QUAD(dx + m->dx + animdx, dy + m->dy + animdy, z, m->scale);
if (m->shader) glUseProgramObjectARB(0);
}
......@@ -641,6 +704,7 @@ static int map_to_screen(lua_State *L)
map_type *map = (map_type*)auxiliar_checkclass(L, "core{map}", 1);
int x = luaL_checknumber(L, 2);
int y = luaL_checknumber(L, 3);
int nb_keyframes = luaL_checknumber(L, 4);
int i = 0, j = 0, z = 0;
/* Enables Depth Testing */
......@@ -663,11 +727,11 @@ static int map_to_screen(lua_State *L)
{
if (map->grids_seens[i][j])
{
display_map_quad(map, dx, dy, z, mo, i, j, map->shown_a * map->grids_seens[i][j], FALSE);
display_map_quad(map, dx, dy, z, mo, i, j, map->shown_a * map->grids_seens[i][j], FALSE, nb_keyframes);
}
else
{
display_map_quad(map, dx, dy, z, mo, i, j, map->obscure_a, TRUE);
display_map_quad(map, dx, dy, z, mo, i, j, map->obscure_a, TRUE, nb_keyframes);
}
}
}
......@@ -874,6 +938,8 @@ static const struct luaL_reg map_object_reg[] =
{"invalidate", map_object_invalid},
{"isValid", map_object_is_valid},
{"onSeen", map_object_on_seen},
{"setMoveAnim", map_object_set_move_anim},
{"getMoveAnim", map_object_get_move_anim},
{NULL, NULL},
};
......
......@@ -37,6 +37,8 @@ typedef struct {
bool on_remember;
bool on_unknown;
bool valid;
float oldx, oldy;
int move_step, move_max;
long uid;
} map_object;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment