diff -Naur /home/toil/teeworlds/src/engine/client/backend_sdl.cpp src/engine/client/backend_sdl.cpp
--- /home/toil/teeworlds/src/engine/client/backend_sdl.cpp 2012-06-26 16:53:53.284860687 +1000
+++ src/engine/client/backend_sdl.cpp 2012-07-07 23:49:37.485176348 +1000
@@ -427,6 +427,13 @@
if(pInfo->blit_hw) // ignore_convention
SdlFlags |= SDL_HWACCEL;
+ dbg_assert(!(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
+ || !(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN),
+ "only one of borderless and fullscreen may be activated at the same time");
+
+ if(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
+ SdlFlags |= SDL_NOFRAME;
+
if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN)
SdlFlags |= SDL_FULLSCREEN;
@@ -443,7 +450,7 @@
}
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&CCommandBuffer::INITFLAG_VSYNC ? 1 : 0);
+ SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&IGraphicsBackend::INITFLAG_VSYNC ? 1 : 0);
// set caption
SDL_WM_SetCaption(pName, pName);
diff -Naur /home/toil/teeworlds/src/engine/client/graphics.cpp src/engine/client/graphics.cpp
--- /home/toil/teeworlds/src/engine/client/graphics.cpp 2012-06-26 16:53:53.292861564 +1000
+++ src/engine/client/graphics.cpp 2012-07-07 23:49:37.861176855 +1000
@@ -801,7 +801,15 @@
if(pInfo->blit_hw) // ignore_convention
Flags |= SDL_HWACCEL;
- if(g_Config.m_GfxFullscreen)
+ if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
+ {
+ dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
+ g_Config.m_GfxBorderless = 0;
+ }
+
+ if(g_Config.m_GfxBorderless)
+ Flags |= SDL_NOFRAME;
+ else if(g_Config.m_GfxFullscreen)
Flags |= SDL_FULLSCREEN;
// set gl attributes
diff -Naur /home/toil/teeworlds/src/engine/client/graphics_threaded.cpp src/engine/client/graphics_threaded.cpp
--- /home/toil/teeworlds/src/engine/client/graphics_threaded.cpp 2012-06-26 16:53:53.292861564 +1000
+++ src/engine/client/graphics_threaded.cpp 2012-07-07 23:49:37.489176297 +1000
@@ -712,7 +712,14 @@
int CGraphics_Threaded::IssueInit()
{
int Flags = 0;
- if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
+ if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
+ {
+ dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
+ g_Config.m_GfxBorderless = 0;
+ }
+
+ if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
+ else if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
diff -Naur /home/toil/teeworlds/src/engine/client/graphics_threaded.h src/engine/client/graphics_threaded.h
--- /home/toil/teeworlds/src/engine/client/graphics_threaded.h 2012-06-26 16:53:53.292861564 +1000
+++ src/engine/client/graphics_threaded.h 2012-07-07 23:49:37.489176297 +1000
@@ -98,13 +98,6 @@
enum
{
- INITFLAG_FULLSCREEN = 1,
- INITFLAG_VSYNC = 2,
- INITFLAG_RESIZABLE = 4,
- };
-
- enum
- {
//
PRIMTYPE_INVALID = 0,
PRIMTYPE_LINES,
@@ -300,6 +293,7 @@
INITFLAG_FULLSCREEN = 1,
INITFLAG_VSYNC = 2,
INITFLAG_RESIZABLE = 4,
+ INITFLAG_BORDERLESS = 8,
};
virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags) = 0;
diff -Naur /home/toil/teeworlds/src/engine/client/input.cpp src/engine/client/input.cpp
--- /home/toil/teeworlds/src/engine/client/input.cpp 2012-06-26 16:53:53.292861564 +1000
+++ src/engine/client/input.cpp 2012-07-07 23:49:37.865176246 +1000
@@ -35,6 +35,7 @@
m_InputCurrent = 0;
m_InputGrabbed = 0;
+ m_InputDispatched = false;
m_LastRelease = 0;
m_ReleaseDelta = -1;
@@ -116,10 +117,14 @@
/*if(!input_grabbed && Graphics()->WindowActive())
Input()->MouseModeRelative();*/
- // clear and begin count on the other one
- m_InputCurrent^=1;
- mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
- mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
+ if(m_InputDispatched)
+ {
+ // clear and begin count on the other one
+ m_InputCurrent^=1;
+ mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
+ mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
+ m_InputDispatched = false;
+ }
{
int i;
diff -Naur /home/toil/teeworlds/src/engine/client/serverbrowser.cpp src/engine/client/serverbrowser.cpp
--- /home/toil/teeworlds/src/engine/client/serverbrowser.cpp 2012-06-26 16:53:53.292861564 +1000
+++ src/engine/client/serverbrowser.cpp 2012-07-07 23:49:37.653176620 +1000
@@ -86,7 +86,7 @@
CServerEntry *a = m_ppServerlist[Index1];
CServerEntry *b = m_ppServerlist[Index2];
// make sure empty entries are listed last
- return (a->m_GotInfo && b->m_GotInfo) || (!a->m_GotInfo && !b->m_GotInfo) ? str_comp(a->m_Info.m_aName, b->m_Info.m_aName) < 0 :
+ return (a->m_GotInfo && b->m_GotInfo) || (!a->m_GotInfo && !b->m_GotInfo) ? str_comp_nocase(a->m_Info.m_aName, b->m_Info.m_aName) < 0 :
a->m_GotInfo ? true : false;
}
@@ -94,7 +94,7 @@
{
CServerEntry *a = m_ppServerlist[Index1];
CServerEntry *b = m_ppServerlist[Index2];
- return str_comp(a->m_Info.m_aMap, b->m_Info.m_aMap) < 0;
+ return str_comp_nocase(a->m_Info.m_aMap, b->m_Info.m_aMap) < 0;
}
bool CServerBrowser::SortComparePing(int Index1, int Index2) const
@@ -108,7 +108,7 @@
{
CServerEntry *a = m_ppServerlist[Index1];
CServerEntry *b = m_ppServerlist[Index2];
- return str_comp(a->m_Info.m_aGameType, b->m_Info.m_aGameType) < 0;
+ return str_comp_nocase(a->m_Info.m_aGameType, b->m_Info.m_aGameType) < 0;
}
bool CServerBrowser::SortCompareNumPlayers(int Index1, int Index2) const
diff -Naur /home/toil/teeworlds/src/engine/input.h src/engine/input.h
--- /home/toil/teeworlds/src/engine/input.h 2012-06-26 16:53:53.328861462 +1000
+++ src/engine/input.h 2012-07-07 23:49:37.893182739 +1000
@@ -38,6 +38,7 @@
unsigned char m_aInputState[2][1024];
int m_InputCurrent;
+ bool m_InputDispatched;
int KeyWasPressed(int Key) { return m_aInputState[m_InputCurrent^1][Key]; }
@@ -51,7 +52,11 @@
// events
int NumEvents() const { return m_NumEvents; }
- void ClearEvents() { m_NumEvents = 0; }
+ void ClearEvents()
+ {
+ m_NumEvents = 0;
+ m_InputDispatched = true;
+ }
CEvent GetEvent(int Index) const
{
if(Index < 0 || Index >= m_NumEvents)
diff -Naur /home/toil/teeworlds/src/engine/shared/config_variables.h src/engine/shared/config_variables.h
--- /home/toil/teeworlds/src/engine/shared/config_variables.h 2012-06-26 16:53:53.332860923 +1000
+++ src/engine/shared/config_variables.h 2012-07-07 23:49:37.901191509 +1000
@@ -59,6 +59,7 @@
MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
+MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen")
MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer (fullscreen only)")
MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")
diff -Naur /home/toil/teeworlds/src/engine/shared/memheap.cpp src/engine/shared/memheap.cpp
--- /home/toil/teeworlds/src/engine/shared/memheap.cpp 2012-06-26 16:53:53.340861242 +1000
+++ src/engine/shared/memheap.cpp 2012-07-07 23:49:37.909190850 +1000
@@ -3,7 +3,6 @@
#include
#include "memheap.h"
-static const int CHUNK_SIZE = 1024*64;
// allocates a new chunk to be used
void CHeap::NewChunk()
diff -Naur /home/toil/teeworlds/src/engine/shared/memheap.h src/engine/shared/memheap.h
--- /home/toil/teeworlds/src/engine/shared/memheap.h 2012-06-26 16:53:53.340861242 +1000
+++ src/engine/shared/memheap.h 2012-07-07 23:49:37.909190850 +1000
@@ -15,7 +15,7 @@
enum
{
// how large each chunk should be
- CHUNK_SIZE = 1025*64,
+ CHUNK_SIZE = 1024*64,
};
CChunk *m_pCurrent;
diff -Naur /home/toil/teeworlds/src/game/client/components/menus.h src/game/client/components/menus.h
--- /home/toil/teeworlds/src/game/client/components/menus.h 2012-06-26 16:53:53.360863645 +1000
+++ src/game/client/components/menus.h 2012-07-07 23:49:37.929676066 +1000
@@ -218,11 +218,11 @@
return false;
else
{
- int Result = str_comp(m_pFriendInfo->m_aName, Other.m_pFriendInfo->m_aName);
+ int Result = str_comp_nocase(m_pFriendInfo->m_aName, Other.m_pFriendInfo->m_aName);
if(Result)
return Result < 0;
else
- return str_comp(m_pFriendInfo->m_aClan, Other.m_pFriendInfo->m_aClan) < 0;
+ return str_comp_nocase(m_pFriendInfo->m_aClan, Other.m_pFriendInfo->m_aClan) < 0;
}
}
};
diff -Naur /home/toil/teeworlds/src/game/client/components/menus_settings.cpp src/game/client/components/menus_settings.cpp
--- /home/toil/teeworlds/src/game/client/components/menus_settings.cpp 2012-06-26 16:53:53.364862128 +1000
+++ src/game/client/components/menus_settings.cpp 2012-07-07 23:49:37.937676315 +1000
@@ -615,6 +615,7 @@
static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth;
static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight;
static int s_GfxColorDepth = g_Config.m_GfxColorDepth;
+ static int s_GfxBorderless = g_Config.m_GfxBorderless;
static int s_GfxFullscreen = g_Config.m_GfxFullscreen;
static int s_GfxVsync = g_Config.m_GfxVsync;
static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples;
@@ -670,9 +671,20 @@
// switches
MainView.HSplitTop(20.0f, &Button, &MainView);
+ if(DoButton_CheckBox(&g_Config.m_GfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
+ {
+ g_Config.m_GfxBorderless ^= 1;
+ if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
+ g_Config.m_GfxFullscreen = 0;
+ CheckSettings = true;
+ }
+
+ MainView.HSplitTop(20.0f, &Button, &MainView);
if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
{
g_Config.m_GfxFullscreen ^= 1;
+ if(g_Config.m_GfxFullscreen && g_Config.m_GfxBorderless)
+ g_Config.m_GfxBorderless = 0;
CheckSettings = true;
}
@@ -715,6 +727,7 @@
if(s_GfxScreenWidth == g_Config.m_GfxScreenWidth &&
s_GfxScreenHeight == g_Config.m_GfxScreenHeight &&
s_GfxColorDepth == g_Config.m_GfxColorDepth &&
+ s_GfxBorderless == g_Config.m_GfxBorderless &&
s_GfxFullscreen == g_Config.m_GfxFullscreen &&
s_GfxVsync == g_Config.m_GfxVsync &&
s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples &&
diff -Naur /home/toil/teeworlds/src/game/client/components/players.cpp src/game/client/components/players.cpp
--- /home/toil/teeworlds/src/game/client/components/players.cpp 2012-06-26 16:53:53.368860821 +1000
+++ src/game/client/components/players.cpp 2012-07-07 23:49:37.941683878 +1000
@@ -272,7 +272,7 @@
}
bool Stationary = Player.m_VelX <= 1 && Player.m_VelX >= -1;
- bool InAir = !Collision()->CheckPoint(Player.m_X, Player.m_Y+16);
+ bool InAir = !(Collision()->CheckPoint(Player.m_X-14, Player.m_Y+16) || Collision()->CheckPoint(Player.m_X+14, Player.m_Y+16));
bool WantOtherDir = (Player.m_Direction == -1 && Vel.x > 0) || (Player.m_Direction == 1 && Vel.x < 0);
// evaluate animation
diff -Naur /home/toil/teeworlds/src/game/client/components/skins.h src/game/client/components/skins.h
--- /home/toil/teeworlds/src/game/client/components/skins.h 2012-06-26 16:53:53.368860821 +1000
+++ src/game/client/components/skins.h 2012-07-07 23:49:37.945691580 +1000
@@ -17,7 +17,7 @@
char m_aName[24];
vec3 m_BloodColor;
- bool operator<(const CSkin &Other) { return str_comp(m_aName, Other.m_aName) < 0; }
+ bool operator<(const CSkin &Other) { return str_comp_nocase(m_aName, Other.m_aName) < 0; }
};
void OnInit();
diff -Naur /home/toil/teeworlds/src/game/collision.cpp src/game/collision.cpp
--- /home/toil/teeworlds/src/game/collision.cpp 2012-06-26 16:53:53.376860790 +1000
+++ src/game/collision.cpp 2012-07-08 00:01:43.141676413 +1000
@@ -26,14 +26,14 @@
m_Width = m_pLayers->GameLayer()->m_Width;
m_Height = m_pLayers->GameLayer()->m_Height;
m_pTiles = static_cast(m_pLayers->Map()->GetData(m_pLayers->GameLayer()->m_Data));
-
+
for(int i = 0; i < m_Width*m_Height; i++)
{
int Index = m_pTiles[i].m_Index;
-
+
if(Index > 128)
continue;
-
+
switch(Index)
{
case TILE_DEATH:
@@ -45,35 +45,64 @@
case TILE_NOHOOK:
m_pTiles[i].m_Index = COLFLAG_SOLID|COLFLAG_NOHOOK;
break;
+ case TILE_SLOPE:
+ {
+ m_pTiles[i].m_Index = COLFLAG_SLOPE;
+ m_pTiles[i].m_Flags = OrientationTile(m_pTiles[i].m_Flags, 1);
+ }
+ break;
+ case TILE_SLOPE_NH:
+ {
+ m_pTiles[i].m_Index = COLFLAG_SLOPE|COLFLAG_NOHOOK;
+ m_pTiles[i].m_Flags = OrientationTile(m_pTiles[i].m_Flags, 1);
+ }
+ break;
default:
m_pTiles[i].m_Index = 0;
}
}
}
-int CCollision::GetTile(int x, int y)
+int CCollision::GetTile(int x, int y, int *pFlags, int *pDx, int *pDy)
{
- int Nx = clamp(x/32, 0, m_Width-1);
- int Ny = clamp(y/32, 0, m_Height-1);
+ int Address = clamp(y/32, 0, m_Height-1)*m_Width + clamp(x/32, 0, m_Width-1);
+ int Index = m_pTiles[Address].m_Index;
+
+ if(Index&COLFLAG_SLOPE)
+ {
+ int Flags = m_pTiles[Address].m_Flags;
+ int Dx = x < 0 ? 31-abs(x)%32 : x%32;
+ int Dy = y < 0 ? 31-abs(y)%32 : y%32;
+
+ if((Flags == 1 && Dy >= Dx) || (Flags == 3 && Dy+Dx <= 31) || (Flags == 5 && Dy <= Dx) || (Flags == 7 && Dy+Dx >= 31))
+ Index |= COLFLAG_SOLID;
+ else if(Index&COLFLAG_NOHOOK)
+ Index ^= COLFLAG_NOHOOK;
+
+ if(pDx) *pDx = Dx;
+ if(pDy) *pDy = Dy;
+ if(pFlags) *pFlags = Flags;
+}
+
+return Index > 128 ? 0 : Index;
- return m_pTiles[Ny*m_Width+Nx].m_Index > 128 ? 0 : m_pTiles[Ny*m_Width+Nx].m_Index;
}
bool CCollision::IsTileSolid(int x, int y)
{
- return GetTile(x, y)&COLFLAG_SOLID;
+ return GetTile(x,y)&COLFLAG_SOLID;
}
// TODO: rewrite this smarter!
int CCollision::IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision)
{
- float Distance = distance(Pos0, Pos1);
- int End(Distance+1);
+ float d = distance(Pos0, Pos1);
+ int End(d+1);
vec2 Last = Pos0;
-
+
for(int i = 0; i < End; i++)
{
- float a = i/Distance;
+ float a = i/d;
vec2 Pos = mix(Pos0, Pos1, a);
if(CheckPoint(Pos.x, Pos.y))
{
@@ -97,52 +126,112 @@
{
if(pBounces)
*pBounces = 0;
-
+
vec2 Pos = *pInoutPos;
- vec2 Vel = *pInoutVel;
- if(CheckPoint(Pos + Vel))
+ vec2 NewPos = Pos + *pInoutVel;
+ int Flags, Index = GetTile(round(NewPos.x), round(NewPos.y), &Flags);
+
+ if(Index&COLFLAG_SOLID)
{
int Affected = 0;
- if(CheckPoint(Pos.x + Vel.x, Pos.y))
+
+ if(Index&COLFLAG_SLOPE)
+ {
+ if(round(NewPos.x)/32 == round(Pos.x)/32 && round(NewPos.y)/32 == round(Pos.y)/32)//not correct, only approximative
+ {
+ vec2 Reflex = vec2(pInoutVel->y, pInoutVel->x); //inverting axisses values
+ if(Flags == 3 || Flags == 7)
+ Reflex *= -1; //inverting sings
+
+ *pInoutVel = Elasticity? Reflex*Elasticity : (*pInoutVel+Reflex)*0.5f;
+ if(pBounces)
+ (*pBounces)++;
+ Affected++;
+
+ return;
+ }
+ }
+
+ if(CheckPoint(NewPos.x, Pos.y))
{
pInoutVel->x *= -Elasticity;
if(pBounces)
- (*pBounces)++;
+ (*pBounces)++;
Affected++;
}
- if(CheckPoint(Pos.x, Pos.y + Vel.y))
+ if(CheckPoint(Pos.x, NewPos.y))
{
pInoutVel->y *= -Elasticity;
if(pBounces)
- (*pBounces)++;
+ (*pBounces)++;
Affected++;
}
-
+
if(Affected == 0)
- {
- pInoutVel->x *= -Elasticity;
- pInoutVel->y *= -Elasticity;
- }
+ *pInoutVel *= -Elasticity;
}
else
{
- *pInoutPos = Pos + Vel;
+ *pInoutPos = NewPos;
}
}
-bool CCollision::TestBox(vec2 Pos, vec2 Size)
+int CCollision::TestBox(vec2 Pos, vec2 Size)
+{// not formatted, sorry :)
+Pos -= Size*0.5f;
+int Flags, Dx, Dy, Index = GetTile(round(Pos.x), round(Pos.y), &Flags, &Dx, &Dy);
+if(Index&COLFLAG_SOLID)
{
- Size *= 0.5f;
- if(CheckPoint(Pos.x-Size.x, Pos.y-Size.y))
- return true;
- if(CheckPoint(Pos.x+Size.x, Pos.y-Size.y))
- return true;
- if(CheckPoint(Pos.x-Size.x, Pos.y+Size.y))
- return true;
- if(CheckPoint(Pos.x+Size.x, Pos.y+Size.y))
- return true;
- return false;
+if(Index&COLFLAG_SLOPE && Flags == 3) return 3;
+else return 64;
+}
+else if(Index&COLFLAG_SLOPE)
+{
+if(Flags == 1 && Dy+Size.y > Dx) return 64; //16|8
+else if(Flags == 5 && Dy < Dx+Size.x) return 64; //32|2
+}
+
+Pos.x += Size.x;
+Index = GetTile(round(Pos.x), round(Pos.y), &Flags, &Dx, &Dy);
+if(Index&COLFLAG_SOLID)
+{
+if(Index&COLFLAG_SLOPE && Flags == 5) return 5;
+else return 64;
+}
+else if(Index&COLFLAG_SLOPE)
+{
+if(Flags == 3 && Dy+Dx < 31+Size.x) return 64; // 32|1
+else if(Flags == 7 && Dy+Size.y+Dx > 31) return 64; // 16|4
+}
+
+Pos.y += Size.y;
+Index = GetTile(round(Pos.x), round(Pos.y), &Flags, &Dx, &Dy);
+if(Index&COLFLAG_SOLID)
+{
+if(Index&COLFLAG_SLOPE && Flags == 7) return 7;
+else return 64;
+}
+else if(Index&COLFLAG_SLOPE)
+{
+if(Flags == 1 && Dy+Size.x > Dx) return 64; // 32|8
+else if(Flags == 5 && Dy-Size.y < Dx) return 64; // 16|2
+}
+
+Pos.x -= Size.x;
+Index = GetTile(round(Pos.x), round(Pos.y), &Flags, &Dx, &Dy);
+if(Index&COLFLAG_SOLID)
+{
+if(Index&COLFLAG_SLOPE && Flags == 1) return 1;
+else return 64;
+}
+else if(Index&COLFLAG_SLOPE)
+{
+if(Flags == 3 && Dy+Dx-Size.y < 31) return 64; // 16|1
+else if(Flags == 7 && Dy+Dx > 31-Size.x) return 64; // 32|4
+}
+
+return 0;
}
void CCollision::MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity)
@@ -150,10 +239,10 @@
// do the move
vec2 Pos = *pInoutPos;
vec2 Vel = *pInoutVel;
-
+
float Distance = length(Vel);
int Max = (int)Distance;
-
+
if(Distance > 0.00001f)
{
//vec2 old_pos = pos;
@@ -163,42 +252,107 @@
//float amount = i/(float)max;
//if(max == 0)
//amount = 0;
-
+
vec2 NewPos = Pos + Vel*Fraction; // TODO: this row is not nice
-
- if(TestBox(vec2(NewPos.x, NewPos.y), Size))
+
+ if(TestBox(NewPos, Size))
{
int Hits = 0;
- if(TestBox(vec2(Pos.x, NewPos.y), Size))
+ int Colliding = TestBox(vec2(NewPos.x, Pos.y), Size);
+ if(Colliding)
{
- NewPos.y = Pos.y;
- Vel.y *= -Elasticity;
+ if(Colliding == 64)
+ Vel.x *= -Elasticity;
+ else if(IntersectSlope(Colliding, &Vel, Elasticity))
+ Pos = vec2(round(Pos.x), round(Pos.y));
+
Hits++;
}
-
- if(TestBox(vec2(NewPos.x, Pos.y), Size))
+
+ Colliding = TestBox(vec2(Pos.x, NewPos.y), Size);
+ if(Colliding)
{
- NewPos.x = Pos.x;
- Vel.x *= -Elasticity;
+ if(Colliding == 64)
+ Vel.y *= -Elasticity;
+ else if(IntersectSlope(Colliding, &Vel, Elasticity))
+ Pos = vec2(round(Pos.x), round(Pos.y));
+
Hits++;
}
-
+
// neither of the tests got a collision.
// this is a real _corner case_!
if(Hits == 0)
- {
- NewPos.y = Pos.y;
- Vel.y *= -Elasticity;
- NewPos.x = Pos.x;
- Vel.x *= -Elasticity;
- }
- }
+ Vel *= -Elasticity;
- Pos = NewPos;
+ }
+ else
+ Pos = NewPos;
}
}
-
+
*pInoutPos = Pos;
*pInoutVel = Vel;
}
+
+int CCollision::OrientationTile(int Flags, int Dir)
+{ //Converts tiles flags to get effective direction drawn in the map editor
+ // Examples Dir(values)[axisses reference]: (0)=to down[x=0:y=1]; (1)=to bottom-right[x=1:y=1]; (2)=to right[x=1:y=0];...
+ if(Dir == 1)
+ {
+ if(Flags&TILEFLAG_ROTATE)
+ {
+ if(Flags&TILEFLAG_HFLIP)
+ Dir = Flags&TILEFLAG_VFLIP? 7 : 5;
+ else
+ Dir = Flags&TILEFLAG_VFLIP? 1 : 3;
+ }
+ else
+ {
+ if(Flags&TILEFLAG_HFLIP)
+ Dir = Flags&TILEFLAG_VFLIP? 5 : 3;
+ else
+ Dir = Flags&TILEFLAG_VFLIP? 7 : 1;
+ }
+ }
+ else if(Dir == 4)//this variant is useless now, but in future coulbe be used
+ {
+ if(Flags&TILEFLAG_ROTATE)
+ Dir = Flags&TILEFLAG_HFLIP? 6 : 2;
+ else
+ Dir = Flags&TILEFLAG_HFLIP? 0 : 4;
+ }
+
+ return Dir;
+}
+
+bool CCollision::IntersectSlope(int Flags, vec2 *pVel, int Elasticity)
+{
+ vec2 Vel = *pVel;
+ if((Flags==1 && Vel.y > Vel.x) || (Flags==3 && Vel.y+Vel.x < 0) || (Flags==5 && Vel.y < Vel.x) || (Flags==7 && Vel.y+Vel.x > 0))
+ {
+ vec2 Reaction = vec2(Vel.y, Vel.x); //inverting axisses values
+ if(Flags == 3 || Flags == 7)
+ Reaction *= -1; //inverting sings
+
+ *pVel = Elasticity? Reaction*Elasticity : (Vel+Reaction)*0.5f;
+ return true;
+ }
+ else
+ return false;
+
+//more general intersection function: maybe useful in future (not formatted)
+/* //equation of the line(AB) in implicit form (ax+by+c=0) analytic geometry
+float a1= Vel.y-Corner.y, b1= Corner.x-Vel.x, c1= -Corner.x*Vel.y; //1 first line: player movement
+float a2= B.y-A.y, b2= A.x-B.x, c2= -A.x*B.y; //2 second line: slope segment
+
+float d = a1*b2-a2*b1;
+
+if(d)//lines are not parallel
+{
+vec2 HitPoint = vec2((b1*c2-b2*c1)/d, (a2*c1-a1*c2)/d);
+}
+else
+return false*/
+}
\ No newline at end of file
diff -Naur /home/toil/teeworlds/src/game/collision.h src/game/collision.h
--- /home/toil/teeworlds/src/game/collision.h 2012-06-26 16:53:53.376860790 +1000
+++ src/game/collision.h 2012-07-07 23:49:37.953689524 +1000
@@ -13,14 +13,16 @@
class CLayers *m_pLayers;
bool IsTileSolid(int x, int y);
- int GetTile(int x, int y);
-
+ int GetTile(int x, int y, int *pFlags=0, int *pDx=0, int *pDy=0);
+ int OrientationTile(int Flags, int Dir);
+ bool IntersectSlope(int Flags, vec2 *pVel, int Elasticity);
public:
enum
{
COLFLAG_SOLID=1,
COLFLAG_DEATH=2,
COLFLAG_NOHOOK=4,
+ COLFLAG_SLOPE=8,
};
CCollision();
@@ -33,7 +35,7 @@
int IntersectLine(vec2 Pos0, vec2 Pos1, vec2 *pOutCollision, vec2 *pOutBeforeCollision);
void MovePoint(vec2 *pInoutPos, vec2 *pInoutVel, float Elasticity, int *pBounces);
void MoveBox(vec2 *pInoutPos, vec2 *pInoutVel, vec2 Size, float Elasticity);
- bool TestBox(vec2 Pos, vec2 Size);
+ int TestBox(vec2 Pos, vec2 Size);
};
#endif
diff -Naur /home/toil/teeworlds/src/game/editor/layer_tiles.cpp src/game/editor/layer_tiles.cpp
--- /home/toil/teeworlds/src/game/editor/layer_tiles.cpp 2012-06-26 16:53:53.380861019 +1000
+++ src/game/editor/layer_tiles.cpp 2012-07-07 23:49:37.665176329 +1000
@@ -220,10 +220,13 @@
m_pTiles[y*m_Width+m_Width-1-x] = Tmp;
}
- if(!m_Game)
- for(int y = 0; y < m_Height; y++)
- for(int x = 0; x < m_Width; x++)
- m_pTiles[y*m_Width+x].m_Flags ^= m_pTiles[y*m_Width+x].m_Flags&TILEFLAG_ROTATE ? TILEFLAG_HFLIP : TILEFLAG_VFLIP;
+ for(int y = 0; y < m_Height; y++)
+ for(int x = 0; x < m_Width; x++)
+ {
+ int N = y*m_Width+x;
+ if(!m_Game || m_pTiles[N].m_Index == TILE_SLOPE || m_pTiles[N].m_Index == TILE_SLOPE_NH)
+ m_pTiles[N].m_Flags ^= m_pTiles[N].m_Flags&TILEFLAG_ROTATE ? TILEFLAG_HFLIP : TILEFLAG_VFLIP;
+ }
}
void CLayerTiles::BrushFlipY()
@@ -236,21 +239,24 @@
m_pTiles[(m_Height-1-y)*m_Width+x] = Tmp;
}
- if(!m_Game)
- for(int y = 0; y < m_Height; y++)
- for(int x = 0; x < m_Width; x++)
- m_pTiles[y*m_Width+x].m_Flags ^= m_pTiles[y*m_Width+x].m_Flags&TILEFLAG_ROTATE ? TILEFLAG_VFLIP : TILEFLAG_HFLIP;
+ for(int y = 0; y < m_Height; y++)
+ for(int x = 0; x < m_Width; x++)
+ {
+ int N = y*m_Width+x;
+ if(!m_Game || m_pTiles[N].m_Index == TILE_SLOPE || m_pTiles[N].m_Index == TILE_SLOPE_NH)
+ m_pTiles[N].m_Flags ^= m_pTiles[N].m_Flags&TILEFLAG_ROTATE ? TILEFLAG_VFLIP : TILEFLAG_HFLIP;
+ }
}
void CLayerTiles::BrushRotate(float Amount)
{
- int Rotation = (round(360.0f*Amount/(pi*2))/90)%4; // 0=0�, 1=90�, 2=180�, 3=270�
+ int Rotation = (round(360.0f*Amount/(pi*2))/90)%4; // 0=0�, 1=90�, 2=180�, 3=270�
if(Rotation < 0)
Rotation +=4;
if(Rotation == 1 || Rotation == 3)
{
- // 90� rotation
+ // 90� rotation
CTile *pTempData = new CTile[m_Width*m_Height];
mem_copy(pTempData, m_pTiles, m_Width*m_Height*sizeof(CTile));
CTile *pDst = m_pTiles;
@@ -258,7 +264,7 @@
for(int y = m_Height-1; y >= 0; --y, ++pDst)
{
*pDst = pTempData[y*m_Width+x];
- if(!m_Game)
+ if(!m_Game || pDst->m_Index == TILE_SLOPE || pDst->m_Index == TILE_SLOPE_NH)
{
if(pDst->m_Flags&TILEFLAG_ROTATE)
pDst->m_Flags ^= (TILEFLAG_HFLIP|TILEFLAG_VFLIP);
diff -Naur /home/toil/teeworlds/src/game/generated/nethash.c src/game/generated/nethash.c
--- /home/toil/teeworlds/src/game/generated/nethash.c 1970-01-01 10:00:00.000000000 +1000
+++ src/game/generated/nethash.c 2012-07-07 23:45:54.225177199 +1000
@@ -0,0 +1 @@
+#define GAME_NETVERSION_HASH "b67d1f1a1eea234e"
diff -Naur /home/toil/teeworlds/src/game/mapitems.h src/game/mapitems.h
--- /home/toil/teeworlds/src/game/mapitems.h 2012-06-26 16:53:53.384860969 +1000
+++ src/game/mapitems.h 2012-07-07 23:53:46.241689194 +1000
@@ -46,7 +46,8 @@
TILE_SOLID,
TILE_DEATH,
TILE_NOHOOK,
-
+ TILE_SLOPE=17,
+ TILE_SLOPE_NH,
TILEFLAG_VFLIP=1,
TILEFLAG_HFLIP=2,
TILEFLAG_OPAQUE=4,
diff -Naur /home/toil/teeworlds/src/game/server/gamecontext.cpp src/game/server/gamecontext.cpp
--- /home/toil/teeworlds/src/game/server/gamecontext.cpp 2012-06-26 16:53:53.392865827 +1000
+++ src/game/server/gamecontext.cpp 2012-07-07 23:49:37.965178275 +1000
@@ -1120,39 +1120,29 @@
if(!pSelf->m_pController->IsTeamplay())
return;
- int CounterRed = 0;
- int CounterBlue = 0;
+ int rnd = 0;
int PlayerTeam = 0;
- for(int i = 0; i < MAX_CLIENTS; ++i)
+ int aPlayer[MAX_CLIENTS];
+
+ for(int i = 0; i < MAX_CLIENTS; i++)
if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
- ++PlayerTeam;
- PlayerTeam = (PlayerTeam+1)/2;
-
+ aPlayer[PlayerTeam++]=i;
+
pSelf->SendChat(-1, CGameContext::CHAT_ALL, "Teams were shuffled");
- for(int i = 0; i < MAX_CLIENTS; ++i)
+ //creating random permutation
+ for(int i = PlayerTeam; i > 1; i--)
{
- if(pSelf->m_apPlayers[i] && pSelf->m_apPlayers[i]->GetTeam() != TEAM_SPECTATORS)
- {
- if(CounterRed == PlayerTeam)
- pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_BLUE, false);
- else if(CounterBlue == PlayerTeam)
- pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_RED, false);
- else
- {
- if(rand() % 2)
- {
- pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_BLUE, false);
- ++CounterBlue;
- }
- else
- {
- pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[i], TEAM_RED, false);
- ++CounterRed;
- }
- }
- }
+ rnd = rand() % i;
+ int tmp = aPlayer[rnd];
+ aPlayer[rnd] = aPlayer[i-1];
+ aPlayer[i-1] = tmp;
}
+ //uneven Number of Players?
+ rnd = PlayerTeam % 2 ? rand() % 2 : 0;
+
+ for(int i = 0; i < PlayerTeam; i++)
+ pSelf->m_pController->DoTeamChange(pSelf->m_apPlayers[aPlayer[i]], i < (PlayerTeam+rnd)/2 ? TEAM_RED : TEAM_BLUE, false);
}
void CGameContext::ConLockTeams(IConsole::IResult *pResult, void *pUserData)
@@ -1458,15 +1448,15 @@
m_Collision.Init(&m_Layers);
// select gametype
- if(str_comp(g_Config.m_SvGametype, "mod") == 0)
+ if(str_comp_nocase(g_Config.m_SvGametype, "mod") == 0)
m_pController = new CGameControllerMOD(this);
- else if(str_comp(g_Config.m_SvGametype, "ctf") == 0)
+ else if(str_comp_nocase(g_Config.m_SvGametype, "ctf") == 0)
m_pController = new CGameControllerCTF(this);
- else if(str_comp(g_Config.m_SvGametype, "lms") == 0)
+ else if(str_comp_nocase(g_Config.m_SvGametype, "lms") == 0)
m_pController = new CGameControllerLMS(this);
- else if(str_comp(g_Config.m_SvGametype, "sur") == 0)
+ else if(str_comp_nocase(g_Config.m_SvGametype, "sur") == 0)
m_pController = new CGameControllerSUR(this);
- else if(str_comp(g_Config.m_SvGametype, "tdm") == 0)
+ else if(str_comp_nocase(g_Config.m_SvGametype, "tdm") == 0)
m_pController = new CGameControllerTDM(this);
else
m_pController = new CGameControllerDM(this);
diff -Naur /home/toil/teeworlds/src/game/server/gamemodes/ctf.cpp src/game/server/gamemodes/ctf.cpp
--- /home/toil/teeworlds/src/game/server/gamemodes/ctf.cpp 2012-06-26 16:53:53.396862075 +1000
+++ src/game/server/gamemodes/ctf.cpp 2012-07-07 23:49:37.969176549 +1000
@@ -287,6 +287,9 @@
{
F->m_Vel.y += GameServer()->m_World.m_Core.m_Tuning.m_Gravity;
GameServer()->Collision()->MoveBox(&F->m_Pos, &F->m_Vel, vec2(F->ms_PhysSize, F->ms_PhysSize), 0.5f);
+
+ if(GameServer()->Collision()->CheckPoint(F->m_Pos.x, F->m_Pos.y+F->ms_PhysSize/2+5))
+ F->m_Vel.x *= GameServer()->m_World.m_Core.m_Tuning.m_GroundFriction;
}
}
}