map.cpp
来自「一个symbian 冒险游戏代码」· C++ 代码 · 共 1,225 行 · 第 1/3 页
CPP
1,225 行
Surface& s = app->sprites[o.spriteIndex];
o.position[0] += m_props.blockStaggerX;
o.position[1] += m_props.blockStaggerY;
o.position[0] += s.offsetX();
o.position[1] += s.offsetY();
if ( GameApp::get()->isHalfResolution() )
{
o.position[0] += s.offsetX();
o.position[1] += s.offsetY();
}
m_spriteTriggers.add( o );
}
void Map::addScreenTrigger( String name, float x, float y, String screen )
{
ScreenTrigger o;
String::cpy( o.name, sizeof(o.name), name );
o.block[0] = Fixf(x);
o.block[1] = Fixf(y);
o.active = true;
GameApp* app = GameApp::get();
o.screenIndex = app->findItem( app->screenNames, app->screenCount, screen.c_str() );
if ( -1 == o.screenIndex )
throwError( Exception( Format( "screen {0} not found from list", screen ) ) );
m_screenTriggers.add( o );
}
void Map::addItemTrigger( String name, float x, float y, String item )
{
ItemTrigger o;
String::cpy( o.name, sizeof(o.name), name );
o.block[0] = Fixf(x);
o.block[1] = Fixf(y);
o.type = ItemTrigger::Add;
String::cpy( o.itemName, sizeof(o.itemName), item );
GameApp* app = GameApp::get();
o.itemIndex = app->findItem( app->spriteNames, app->spriteCount, item.c_str() );
m_itemTriggers.add( o );
}
void Map::removeItemTrigger( String name, float x, float y, String item )
{
ItemTrigger o;
String::cpy( o.name, sizeof(o.name), name );
o.block[0] = Fixf(x);
o.block[1] = Fixf(y);
o.type = ItemTrigger::Remove;
String::cpy( o.itemName, sizeof(o.itemName), item );
GameApp* app = GameApp::get();
o.itemIndex = app->findItem( app->spriteNames, app->spriteCount, item.c_str() );
m_itemTriggers.add( o );
}
float Map::addEnemy( lang::String name, float x, float y, float angle, lang::String type, float hitpoints,
float speed, float attackdamage, float attackskill, float aggression )
{
ASSERT( angle >= 0 && angle <= 360 );
ASSERT( aggression <= 256.f );
Enemy o;
o.m_map = this;
String::cpy( o.m_name, sizeof(o.m_name), name );
o.setBlockPosition( FixVec2(Fixf(x),Fixf(y)) );
o.setDirection( Enemy::getAngleAsDir(Fixf(angle)) );
o.setType( Enemy::toEnemyType(type.c_str()) );
o.setHitPoints( Fixf(hitpoints) );
o.m_speed = Fixf(speed);
o.m_attackDamage = Fixf(attackdamage);
o.m_attackSkill = Fixf(attackskill/100.f);
o.m_aggression = Fixf(aggression);
m_enemies.add( o );
return (float)( m_enemies.size()-1 );
}
void Map::disableTrigger( String name )
{
Trigger* triggerlist[128]; // note the limit
int triggers = getTriggers( name.c_str(), triggerlist, 128 );
for ( int i = 0 ; i < triggers ; ++i )
triggerlist[i]->flags &= ~Trigger::FLAG_ENABLED;
}
//-------
#endif
int Map::getTriggers( const char* name, Trigger** triggerlist, int size )
{
int triggers = 0;
for ( int i = 0 ; i < m_levelTriggers.size() ; ++i )
if ( !strcmp(name,m_levelTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_levelTriggers[i];
}
for ( int i = 0 ; i < m_textTriggers.size() ; ++i )
if ( !strcmp(name,m_textTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_textTriggers[i];
}
for ( int i = 0 ; i < m_enableTriggers.size() ; ++i )
if ( !strcmp(name,m_enableTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_enableTriggers[i];
}
for ( int i = 0 ; i < m_spriteTriggers.size() ; ++i )
if ( !strcmp(name,m_spriteTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_spriteTriggers[i];
}
for ( int i = 0 ; i < m_screenTriggers.size() ; ++i )
if ( !strcmp(name,m_screenTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_screenTriggers[i];
}
for ( int i = 0 ; i < m_itemTriggers.size() ; ++i )
if ( !strcmp(name,m_itemTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_itemTriggers[i];
}
for ( int i = 0 ; i < m_charStateTriggers.size() ; ++i )
if ( !strcmp(name,m_charStateTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_charStateTriggers[i];
}
for ( int i = 0 ; i < m_specialTriggers.size() ; ++i )
if ( !strcmp(name,m_specialTriggers[i].name) )
{
assert( triggers < size );
triggerlist[triggers++] = &m_specialTriggers[i];
}
return triggers;
}
void Map::addPlayer( MapObject* obj )
{
addObject( obj );
obj->setBlockPosition( m_playerStartPosition );
obj->setDirection( MapObject::DIR_0 );
m_player = obj;
}
void Map::removePlayer()
{
removeObject( m_player );
m_player = 0;
}
void Map::addObject( MapObject* obj )
{
assert( m_objs < MAX_OBJECTS );
#ifdef WIN32_EXTRA_CHECKS
for ( int i = 0 ; i < m_objs ; ++i )
{
assert( m_objlist[i] != obj );
}
#endif
obj->m_map = this;
m_objlist[m_objs++] = obj;
}
void Map::removeObject( MapObject* obj )
{
for ( int i = 0 ; i < m_objs ; ++i )
{
if ( m_objlist[i] == obj )
{
m_objlist[i] = m_objlist[m_objs-1];
--m_objs;
break;
}
}
}
void Map::computeIntermediates()
{
// bound visible area
int x1=0, y1=0;
int x0=mapWidth(), y0=mapHeight();
for ( int y = 0 ; y < mapHeight() ; ++y )
{
for ( int x = 0 ; x < mapWidth() ; ++x )
{
if ( getMapBlock(x,y) != 0 )
{
if ( x > x1 )
x1 = x;
if ( x < x0 )
x0 = x;
if ( y > y1 )
y1 = y;
if ( y < y0 )
y0 = y;
}
}
}
dprintf( "visible area: (%d,%d)-(%d,%d)\n", x0,y0,x1,y1 );
m_boundX0 = x0;
m_boundX1 = x1;
m_boundY0 = y0;
m_boundY1 = y1;
}
int Map::getCollisionLines( int x, int y, FixVec2* linelist ) const
{
int coll = -1;
if ( isMapBlock(x,y) )
{
const BlockInfo& bi = getBlockInfo( getMapBlock(x,y) );
if ( bi.bg[0] != 0 )
coll = bi.coll;
}
const Fix sx = Fix::fromInt( blockStaggerX() );
const Fix sy = Fix::fromInt( blockStaggerY() );
const Fix bw = Fix::fromInt( blockWidth() );
const Fix bh = Fix::fromInt( blockHeight() );
const FixVec2 origin( blockToPixel( FixVec2(Fix::fromInt(x),Fix::fromInt(y)) ) );
int c = 0;
if ( coll & BlockInfo::COLL_TOPLEFT )
{
linelist[c++] = FixVec2(Fixf(0),sy) + origin;
linelist[c++] = FixVec2(sx,Fixf(0)) + origin;
}
if ( coll & BlockInfo::COLL_TOPRIGHT )
{
FixVec2 s(sx,Fixf(0));
FixVec2 e(bw,sy);
linelist[c++] = s + origin;
linelist[c++] = e + origin;
}
if ( coll & BlockInfo::COLL_BOTTOMRIGHT )
{
linelist[c++] = FixVec2(bw,sy) + origin;
linelist[c++] = FixVec2(sx,bh) + origin;
}
if ( coll & BlockInfo::COLL_BOTTOMLEFT )
{
linelist[c++] = FixVec2(sx,bh) + origin;
linelist[c++] = FixVec2(Fixf(0),sy) + origin;
}
return c>>1;
}
bool Map::testPointCollision( const FixVec2& pos, const FixVec2& delta, const FixVec2& dir ) const
{
FixVec2 left( -dir.y, dir.x );
FixVec2 pos1 = pos + delta + dir*Fixf(5.f);
FixVec2 pointlist[] =
{
pos-dir*Fixf(5.f), pos, pos1, pos1+dir*Fixf(5.f),
pos-dir*Fixf(5.f)-left, pos-left, pos1-left, pos1+dir*Fixf(5.f)-left,
pos-dir*Fixf(5.f)+left, pos+left, pos1+left, pos1+dir*Fixf(5.f)+left
};
const int POINTS = sizeof(pointlist) / sizeof(pointlist[0]);
int blocklist[100];
int blocks = 0;
for ( int i = 0 ; i < POINTS ; ++i )
{
FixVec2 b = pixelToBlock( pointlist[i] );
assert( blocks < int(sizeof(blocklist) / sizeof(blocklist[0])) );
blocklist[blocks++] = b.x.toInt() + (b.y.toInt()<<16);
}
LANG_SORT( blocklist, blocklist+blocks );
blocks = unique( blocklist, blocklist+blocks ) - blocklist;
const int MAX_LINES = 64;
FixVec2 linelist[MAX_LINES*2];
int lines = 0;
for ( int i = 0 ; i < blocks ; ++i )
{
assert( lines+4 <= MAX_LINES );
lines += getCollisionLines( blocklist[i]&0xFFFF, (blocklist[i]>>16)&0xFFFF, linelist + lines+lines );
}
for ( int i = 0 ; i < lines ; ++i )
{
const FixVec2& p0 = linelist[i+i];
const FixVec2& p1 = linelist[i+i+1];
#ifdef DEBUG_INFO
viewportLines.add( p0, p1, 0xF );
#endif
if ( FixUtil::testLineLineIntersection(pos,pos1,p0,p1) ||
FixUtil::testLineLineIntersection(pos-left,pos+left,p0,p1) ||
FixUtil::testLineLineIntersection(pos1-left,pos1+left,p0,p1) ||
FixUtil::testLineLineIntersection(pos-left,pos1-left,p0,p1) ||
FixUtil::testLineLineIntersection(pos+left,pos1+left,p0,p1) )
return true;
}
return false;
}
lang::Array<Enemy> Map::enemies() const
{
return m_enemies;
}
FixVec2 Map::blockToPixel( const FixVec2& pos ) const
{
FixVec2 p( pos.x * Fix::fromInt(blockWidth()),
pos.y * Fix::fromInt(blockStaggerY()) );
if ( pos.y.toInt() & 1 )
p.x += Fix::fromInt( blockStaggerX() );
return p;
}
FixVec2 Map::pixelToBlock( const FixVec2& pos, bool* out_rightHalf, bool* out_lowerHalf, bool* out_oddBlock ) const
{
div_t x = div( pos.x.toInt(), blockWidth() );
div_t y = div( pos.y.toInt(), blockHeight() );
bool rightHalf = false;
bool lowerHalf = false;
bool oddBlock = false;
Fix px = Fix::fromInt( x.rem );
Fix py = Fix::fromInt( y.rem );
const Fix sx = Fix::fromInt( blockStaggerX() );
const Fix sy = Fix::fromInt( blockStaggerY() );
const Fix bw = Fix::fromInt( blockWidth() );
const Fix bh = Fix::fromInt( blockHeight() );
FixVec2 line[] =
{
FixVec2(Fixf(0),sy),
FixVec2(sx,Fixf(0)),
FixVec2(bw,sy),
FixVec2(sx,bh)
};
int bx = x.quot;
int by = y.quot << 1;
if ( !FixUtil::getPointLineSide(px,py,line[0],line[1]) )
{
--bx;
--by;
rightHalf = true;
lowerHalf = true;
oddBlock = true;
}
else if ( !FixUtil::getPointLineSide(px,py,line[1],line[2]) )
{
--by;
rightHalf = false;
lowerHalf = true;
oddBlock = true;
}
else if ( !FixUtil::getPointLineSide(px,py,line[2],line[3]) )
{
++by;
rightHalf = true;
lowerHalf = false;
oddBlock = true;
}
else if ( !FixUtil::getPointLineSide(px,py,line[3],line[0]) )
{
--bx;
++by;
rightHalf = false;
lowerHalf = false;
oddBlock = true;
}
else
{
rightHalf = ( x.rem > blockStaggerX() );
lowerHalf = ( y.rem > blockStaggerY() );
oddBlock = false;
}
if ( out_rightHalf ) *out_rightHalf = rightHalf;
if ( out_lowerHalf ) *out_lowerHalf = lowerHalf;
if ( out_oddBlock ) *out_oddBlock = oddBlock;
return FixVec2( Fix::fromInt(bx), Fix::fromInt(by) );
}
// End of file
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?