Jump to content

  • Log In with Google      Sign In   
  • Create Account

We're offering banner ads on our site from just $5!

1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Finalspace

Member Since 29 Mar 2012
Online Last Active Today, 03:57 AM

#5198903 Chain shapes vs particles - need fast broadphase

Posted by Finalspace on Yesterday, 02:36 AM

Hi there,

 

i have implemented a particle engine with one-way collisions against box2d chain shapes (chained line segments).

Its working fine and my contact solver solves the penetration successfully, but...

...i am using a O(N^2) approach to detect any possible combination for every frame which obviously is very slow.

 

Thats n * (body + n * line segments) * n * particle... too much to test against it. Even with 1200~ particles against 15 chain shapes (up to 30 edges) reduces the framerate to 2.x.

 

Therefore i really need a broadphase technique which drastically reduces the body <> line segment checks. Testing just the fixture of the chain shape by AABB does not help me at all, because my line segment geometry is all over the place. Mostly covering half of the map, cause the chain shapes are built using the traced outlines of a tilemap. It may start at the top left corner and ends at the bottom right cornor in worst case scenarios.

 

What broadphase techniques would work for that problem?

 

Thanks in advance,

Final




#5189102 How to create line segments from tile map outlines

Posted by Finalspace on 25 October 2014 - 12:37 PM

Hi there,

 

i successfully implemented the "Moore Neighborhood" algorythmn to calculate the contours of a tile map, which gives me every tile-outline in clockwise direction. Now i want to create line segments out of it - from edge to edge, but have trouble to figure a algorythmn to solve this. A tile may create/continue two lines in parallel, change directions...

 

This is what i have:

 

TilemapOutlineContour_.png

The black number with the arrow beneath indicates the starting tile including the direction to the next tile.

The colored lines indicates the "tile outline" detected by the algorythmn - i call this "chain" and this goes around clockwise until a tile already visited is found.

 

A chain have just a list of tile coords in vec2 format, something like this:

 

chain {

  tiles: [Vec2, Vec2, Vec2,...]

};

 

This is what i somehow want:

 

TilemapLines.png

 

Any idea?




#5181323 Why using std::string when you can create it yourself...

Posted by Finalspace on 18 September 2014 - 12:29 PM

I am not sure why or what was going on my mind, while creating this "dishy" code somewhere around 2005 where i started to learn c/c++ tongue.png

But this is ridiculous and if i remember correctly, there was memory leaks in it - have fun to find it...

 

Source file:

#include "r3d_string.h"
#include "r3d_global.h"

// Static string

sR3DStaticString::sR3DStaticString()
{
    data[0] = '\0';
}

sR3DStaticString::sR3DStaticString(const char* str)
{
    data[0] = '\0';
    if (strlen(str) > 0)
        AddTo((char*)str);
}

sR3DStaticString::sR3DStaticString(const sR3DStaticString &s)
{
    data[0] = '\0';
    if (strlen(s.data) > 0)
        AddTo(s.data);
}

bool sR3DStaticString::operator == (const char* cmpstr)
{
    return StaticStringCompare(*this, cmpstr) == 0;
}

bool sR3DStaticString::operator == (const sR3DStaticString &s)
{
    return StaticStringCompare(*this, s) == 0;
}

void sR3DStaticString::operator += (const char addc)
{
    char buf[2];
    buf[0] = addc;
    buf[1] = '\0';
    AddTo((char*)buf);
}

void sR3DStaticString::operator += (const char* addstr)
{
    AddTo((char*)addstr);
}

void sR3DStaticString::operator += (const sR3DStaticString &s)
{
    AddTo(s.data);
}

void sR3DStaticString::Clear()
{
    data[0] = '\0';
}

void sR3DStaticString::AddTo(const char* addstr)
{
    strcat(data, addstr);
    data[strlen(data)] = '\0';
}

void sR3DStaticString::AddTo(const char* addstr, const int len)
{
    strncat(data, addstr, len);
    data[strlen(data)] = '\0';
}

void sR3DStaticString::ReplaceChar(const char oldchar, const char newchar)
{
    for (int i = 0; i < strlen(data); i++)
        if (data[i] == oldchar) data[i] = newchar;
}

void sR3DStaticString::AddTrailingPathDelimiter()
{
    if (strlen(data) > 0)
        if (data[strlen(data)-1] != '/')
            AddTo("/");
}

int sR3DStaticString::Pos(const char* substr)
{
    int i = 1;
    char* pch = data;
    while (*pch)
    {
        if (strncmp(pch, substr, strlen(substr)) == 0) return i;
        pch++;
        i++;
    }
    return 0;
}

int sR3DStaticString::Delete(int start, int to)
{
    sR3DStaticString news = "";
    for (int i = 1; i < strlen(data)+1; i++)
    {
        if ((i < start) || (i > to))
            news+=data[i-1];
    }
    if (news.Len() != strlen(data))
    {
        Clear();
        AddTo(news.data);
    }
    return to-start;
}

int sR3DStaticString::RemoveComments()
{
    int commentpos = Pos("//");
    if (commentpos > 0)
        return Delete(commentpos, strlen(data)+1);
    else
        return 0;
}

sR3DStaticString operator + (const sR3DStaticString &s1, const sR3DStaticString  &s2)
{
    char buffer[255];
    buffer[0] = '\0';
    strcat(buffer, s1.data);
    strcat(buffer, s2.data);
    buffer[strlen(buffer)] = '\0';
    return sR3DStaticString(buffer);
}

sR3DStaticString operator + (const sR3DStaticString &s, const char* value)
{
    char buffer[255];
    buffer[0] = '\0';
    strcat(buffer, s.data);
    strcat(buffer, value);
    buffer[strlen(buffer)] = '\0';
    return sR3DStaticString(buffer);
}

sR3DStaticString StaticStringCopy(char* str, int from, int to)
{
    sR3DStaticString newstr;

    // Check if from and to is in range
    if (((from > 0) && (from <= strlen(str))) &&
        ((to > 0) && (to <= strlen(str))))
    {
        int realfrom = from-1;
        int realto = to-1;
        int len = (to - from)+1;
        char* sptr = str;

        // Only left to right allowed
        if (from <= to)
        {
            sptr+=realfrom;
            char m[255];
            strncpy(m, sptr, len);
            m[len] = '\0';
            newstr.AddTo(m);
            free(m);
        }
    }
    return newstr;
}

int StaticStringCompare(const sR3DStaticString &str1, const char* str2)
{
    if (strlen(str1.data) == strlen(str2))
        return strcmp(str1.data,(char*) str2);
    else
        return -1;
}

int StaticStringCompare(const sR3DStaticString &str1, const sR3DStaticString &str2)
{
    if (strlen(str1.data) == strlen(str2.data))
        return strcmp(str1.data,str2.data);
    else
        return -1;
}

sR3DStaticString ExtractFilePath(char* S)
{
    sR3DStaticString res = "";
    int i,j,k;
    k = 0;
    j = strlen(S);
    for (i = j; i >= 1; i--)
    {
        if ((S[i] == '\\') || (S[i] == '/') || (S[i] == ':'))
        {
            k = i;
            break;
        }
    }
    if (k > 0) res.AddTo(S, k);
    return res;
}

sR3DStaticString ExtractFileNameWithoutExt(char* S)
{
    sR3DStaticString res = "";
    int i,j,k;
    k = 0;
    j = strlen(S);
    for (i = j; i >= 1; i--)
    {
        if (S[i] == '.')
        {
            k = i;
            break;
        }
    }
    if (k > 0) res.AddTo(S, k);
    return res;
}

// Dynamic

sR3DString::sR3DString()
{
    data = NULL;
    datalen = 0;
    len = 0;
}

sR3DString::sR3DString(const char* str)
{
    data = NULL;
    datalen = 0;
    len = 0;
    AddTo((char*)str);
}

sR3DString::sR3DString(const sR3DString &s)
{
    data = NULL;
    datalen = 0;
    len = 0;
    AddTo(s.data);
}

sR3DString::~sR3DString(void)
{
    Clear();
}

bool sR3DString::operator == (const char* cmpstr)
{
    return StringCompare(*this, cmpstr) == 0;
}

bool sR3DString::operator == (const sR3DString &s)
{
    return StringCompare(*this, s) == 0;
}

void sR3DString::operator += (const char addc)
{
    char buf[2];
    buf[0] = addc;
    buf[1] = '\0';
    AddTo((char*)buf);
}

void sR3DString::operator += (const char* addstr)
{
    AddTo((char*)addstr);
}

void sR3DString::operator += (const sR3DString &s)
{
    AddTo(s.data);
}

void sR3DString::Clear()
{
    if (data) free(data);
    datalen = 0;
}

void sR3DString::AddTo(const char* addstr)
{
    if (strlen(addstr) > 0)
    {
        if (datalen > 0)
        {
            // Save and kill data
            int oldlen = strlen(data);
            int olddatalen = sizeof(char) * oldlen+1;
            char* saved = (char*) malloc(olddatalen);
            memset(saved, 0, olddatalen);
            strncpy(saved, data, oldlen);
            saved[oldlen] = '\0';
            free(data);

            // Create new one and add old+new
            len = oldlen + strlen(addstr);
            datalen = sizeof(char) * len+1;
            data = (char*) malloc(datalen);
            memset(data, 0, datalen);
            strncpy(data, saved, oldlen);
            strcat(data, addstr);
            data[len] = '\0';
            free(saved);
        } else {
            // Create new one
            len = strlen(addstr);
            datalen = sizeof(char) * len+1;
            data = (char*) malloc(datalen);
            strncpy(data, addstr, len);
            data[len] = '\0';
        }
    }
}

void sR3DString::Alloc(const int newlen)
{
    Clear();
    datalen = newlen+1;
    len = newlen;
    data = (char*) malloc(datalen);
    data[0] = '\0';
}

sR3DString operator + (const sR3DString &s1, const sR3DString  &s2)
{
    sR3DString* newstr = new sR3DString();
    newstr->AddTo(s1.data);
    newstr->AddTo(s2.data);
    return *newstr;
}

sR3DString operator + (const sR3DString &s, const char* value)
{
    sR3DString* newstr = new sR3DString();
    newstr->AddTo(s.data);
    newstr->AddTo((char*)value);
    return *newstr;
}

sR3DString StringCopy(char* str, int from, int to)
{
    sR3DString* newstr = new sR3DString();

    // Check if from and to is in range
    if (((from > 0) && (from <= strlen(str))) &&
        ((to > 0) && (to <= strlen(str))))
    {
        int realfrom = from-1;
        int realto = to-1;
        int len = (to - from)+1;
        char* sptr = str;

        // Only left to right allowed
        if (from <= to)
        {
            sptr+=realfrom;
            char* m = (char*)malloc(sizeof(char) * len+1);
            strncpy(m, sptr, len);
            m[len] = '\0';
            newstr->AddTo(m);
            free(m);
        }

    }
    return *newstr;
}

int StringCompare(const sR3DString &str1, const char* str2)
{
    if (strlen(str1.data) == strlen(str2))
        return strcmp(str1.data,(char*) str2);
    else
        return -1;
}

int StringCompare(const sR3DString &str1, const sR3DString &str2)
{
    if (strlen(str1.data) == strlen(str2.data))
        return strcmp(str1.data,str2.data);
    else
        return -1;
}

Header file:

#ifndef _R3D_STRING_H
#define _R3D_STRING_H

#include <stdlib.h>
#include <string.h>

// Static string

struct sR3DStaticString
{
    char data[255];
    sR3DStaticString();
    sR3DStaticString(const char* addstr);
    sR3DStaticString(const sR3DStaticString &s);
    void Clear();
	void AddTo(const char* addstr);
	void AddTo(const char* addstr, const int len);
	void Terminate() { int l = strlen(data); data[l] = '\0'; }
    void ReplaceChar(const char oldchar, const char newchar);
    void AddTrailingPathDelimiter();
    int Pos(const char* substr);
    int Delete(int start, int to);
    int RemoveComments();
	int Len() { return strlen(data); }
	bool operator == (const char* cmpstr);
	bool operator == (const sR3DStaticString &s);
	void operator += (const char addc);
	void operator += (const char* addstr);
	void operator += (const sR3DStaticString &s);
};

sR3DStaticString operator + (const sR3DStaticString &s1, const sR3DStaticString  &s2);
sR3DStaticString operator + (const sR3DStaticString &s, const char* value);

sR3DStaticString StaticStringCopy(char* str, int from, int to);
int StaticStringCompare(const sR3DStaticString &str1, const char* str2);
int StaticStringCompare(const sR3DStaticString &str1, const sR3DStaticString &str2);
sR3DStaticString ExtractFilePath(char* S);
sR3DStaticString ExtractFileNameWithoutExt(char* S);

// Dynamic string

struct sR3DString
{
    char* data;
    int datalen;
    int len;
    sR3DString();
    sR3DString(const char* addstr);
    sR3DString(const sR3DString &s);
    ~sR3DString(void);
    void Clear();
	void AddTo(const char* addstr);
	void Alloc(const int newlen);
	void Terminate() { len = strlen(data); data[len] = '\0'; }
	//int Len() { return strlen(data); }
	bool operator == (const char* cmpstr);
	bool operator == (const sR3DString &s);
	void operator += (const char addc);
	void operator += (const char* addstr);
	void operator += (const sR3DString &s);
};

sR3DString operator + (const sR3DString &s1, const sR3DString  &s2);
sR3DString operator + (const sR3DString &s, const char* value);

sR3DString StringCopy(char* str, int from, int to);
int StringCompare(const sR3DString &str1, const char* str2);
int StringCompare(const sR3DString &str1, const sR3DString &str2);

#endif /* _R3D_STRING_H */



#5180396 2D Platformer Jumping Problems

Posted by Finalspace on 15 September 2014 - 01:27 AM

 

I am having a little trouble getting the jumping physics right in a 2D platformer I'm working on. What I'm trying to do is set an impulse value, and then let the gravity force slow it down, and eventually reverse it, but it isn't quite working. The result I'm seeing is the player instantly appears at the peak of the jump, and then begins to fall. I'm sure I'm doing something wrong but I'm not seeing it. My update step looks like this:

update(double time)
{
   ddx_ = (forceX_ / mass_) * time;
   ddy_ = (forceY_ / mass_) * time;

   impulseX_ *= time;
   impulseY_ *= time;

   dx_ += (ddx_ + impulseX_);
   dy_ += (ddy_ + impulseY_);

   dx_ += (dx_ * linearDampX_);
   dy_ += (dy_ * linearDampY_);

   dx_ *= time;
   dy_ *= time;

   x_ += dx_;
   y_ += dy_;

   // Impulse should only be set in one update step.
   impulseX_ = 0.0;
   impulseY_ = 0.0;
}

 

I am not sure what is about, but this look very confusing.

 

An typical update step in any game may look like this:

 

You have "velocity" (Acceleration over the entity/player lifetime - is there are no force or impulse this stays forever in that current state)

You have "force" (A force accumulator with applied forces, like gravity to achieve "jumping" - which is cleared after the update steps)

You have "position" your actual position you want to integrate to

 

Then its just a simple integration - which works for platformers very well:

 

acceleration = (force / mass)

velocity += acceleration * delta time

position += velocity * deltatime

 

If you need damping you just "damp" the velocity like this - before applying to the position:

velocity *= 0.99

 

Of course there are other ways to do damping - like for example in a particle simulation, i use this: 

velocity *= pow(0.99, delta time)

which works better (depends on the style of physics you are aiming for):

 

And a very good tip: Do not shorten variable names! Its confusing for other guys and will also most confuse yourself when you read it years later.

 

One last thing, jumping may be done using an upward impulse (instant change in velocity) which is as simple as this:

velocity += impulse




#5175052 Me my motivation and my game-programmers life

Posted by Finalspace on 20 August 2014 - 10:36 AM

Hello there,

 

that title is a little weird i know, but it describes it perfectly:

 

I am developing software since i was 6 or something - started with basic on the C64 and had no understanding what i was doing there, how it works, what programming is etc. I was just fooling around, trying to modify existing codes and see what changes. A bit later in the starting of the dos-age, i was creating simple text-based games with BATCH-files using the choice command. After that my interests of creating games was starting to grow and this was also the turning point for me which has leads me into a programming-career. Now i am a professional software engineer since over 10 years and also have 10 years additional programming experience as creating software, websites, services as a hobby.

 

But, in all that times i never ever finished one damn game. I only have made hundreds of prototypes, technology demos and applications but never got to a point where i could call that a game. Today i understand mostly how a game is built, what technologies may be used or need to be created and i have a good understanding what a game engine are - thanks to the internet and books and such.

 

Now i comes to the actual question/problem i have:

I have made several game-prototypes which got to a state where you can see a bit of the game - no good graphics at all, but basic stuff was working fine so far and then... i just lost the motivation and dont know what to do anymore. Thats really depressing, because it happens all the time and really want to get over it. Its like loosing the grip how to proceed, what to do next - just feeling overwhelmed even with good progress :-( Even now i have a prototype for a game again which looks a bit like a platformer now - i can jump collide etc, but i am nearly at the point where i get overwhelmed and starts to get unmotivated. I know the time may be the biggest factor after all, cause i dont have much of it - have 2 kids and work as a software-developer on a daily basis - so i just have a few hours for each week.

 

Dont get me wrong, i think from the programming perspective this should be no problem at all with my experience, but from the organization-perspective it may be a complete wrong approach i do - i am not sure...

 

My current project is a medium-sized game with a design document which all the relevant game ideas and such and i have a digital todo-list like this - thats it:

Starting today 2014-08-14 - this is the new TODO-LIST !!!

Every task here must not be removed and will just be marked as [DONE] when its done.
Tasks will only be removed when is really not needed anymore.
Done main tasks will be moved to the other done tasks - undone tasks are the bottom!
There are no difference between engine and game, everything is just for the game!
Tasks may classify the state of funniness - like how boring it is, or how interesting etc.
Tasks may have sub-tasks and sub-tasks can have sub-tasks as well, etc.
If a task have no brackets at the start - then its just a "hint" / "information" and no real task
New tasks are to be placed at the bottom!

!!!! DO NOT GET TO TECHNICAL !!!!

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

[DONE] Integrate bitmap font creation in the editor (rather boring)
	-> [DONE] Create a simple ui for font selection and an image preview panel
	-> [DONE] Create a bitmap font texture for a given font and size
	-> [DONE] Convert created font chars to a signed distance field
	-> [DONE] Fix missing alpha channel in final bitmap font

[DONE] Create a simple LWJGL sample for drawing text using bitmap fonts (partly fun)
	-> [DONE] Drawing a single letter with the on-the-fly created bitmap font
	-> [DONE] Drawing more letters
	-> [DONE] Fix letter advance calculation
	-> [DONE] Create a simple shader for the signed distance field rendering
	-> [DONE] Create a good shader for the signed distance field rendering
	-> [DONE] Make a good test example "The quick brown fox jumps over the lazy dog" with multiple font sizes
	  
[	] Save font asset from the editor
	-> [DONE] Save font files images/font description onto the filesystem
	-> [DONE] Move font file saving into the asset utils

[DONE] Add a fps counter on the top left corner (partly fun)
	-> [DONE] Create a HUD component
	-> HUD components have just a bunch of labels with a relative position, a text and v/h alignment
	-> The fps counter is a label in a hud component
	-> [DONE] Create a HUD system which renders the HUD - always in orthographic mode
	-> [DONE] Fix wrong aspect ratio in font rendering
	-> [DONE] Implement text alignment and block alignment
	-> [DONE] Use drawElements instead of drawVertexArray
	
[	] Fixing internal edges collisions using b2edge (boring)
	-> [DONE] Set a bit of restitution to the static body to fix this issue for now
	-> [	] Calculate the outline of the entire level and create the edges instead of boxes

[	] Improve player behavior (somehow boring)
	-> [	] Player movement is still too slow and is not perfect
	-> [	] Player double jumps bounce only when pushing against the wall
		
[	] Tileset mapping to ids (rather boring)
	-> Currently there is no mapping - the first tile index in the platform layer is always solid
	-> [	] Create mapping file structures for defining tilesets and map tile indices to an string key - this key maps to a template 
	-> [	] Create entity template file structure. This is used to automatically create entities with all its components, including material and behaviors. 
	
[	] Drawing cubes for tiles instead of rects (a bit fun)
	-> No idea where to store the vbo/texture instances to not hurt performance
	-> [	] Just draw a blue-chess-like "test"-textured cube like in HL2
	-> [	] 6 Textures per cube (Z-Front and Z-Back, Left and right, Top and bottom)
	-> [	] Drawing the textures like in HL or Quake - repeat, texcoord calculation based on original pixels
	-> [	] Improve performance by sorting the textures - to reduce draw calls and switch states

[	] Complete level loading in the engine - not in the game code! (boring)
	-> [	] Loading tilesets and mappings
	-> [	] Creating collider edge shapes for the level outline
	-> [	] Creating entities like triggers, traps, jumppads etc. from templates -> tile mappings
	
[	] Restrict the camera to a certain area (rather boring)
	-> When camera-area hits the boundary-area (restriction) the player target movemenent stops for the axis.
	-> When the player is in the half camera-area beside the boundary area then movement for the given axis starts moving again.

[	] Fix rendering lagginess by using position interpolation in the game loop (extremely boring)
	-> [	] Keep track of latest position/orientation somehow - not sure where? Transform? Do not touch the physics system for that!
	-> Must happen before every update system!
	
[	] Adding lights (starts boring but will get fun in later states)
	-> Lights are entities as well
	-> [	] Single point light (Look into the OpenGL ES 2.0 Book!)
	-> [	] Placing point lights with the editor on a separate layer
	-> [	] Specular support for point lights
	-> [	] Spot lights
		
[	] Create jumppad (seems to be fun)
	-> Entity must have at least one shape which is flagged as sensor
	-> Entity must have a physics component
	-> Entity must have a transform component
	-> [	] Behavior needs to be extended to accept incoming collisions/overlappings
	-> [	] Create jumppad behavior class and add a velocity impulse when triggered - take trigger states in account (when other entity has not triggered yet and triggers it and still penetrates there should be no impulse!)

Can you guys give me some hints how to organize a myself better to not feel overwhelmed on creating a game, cause i think the main problem i have is to organize myself.

 

Thanks for reading.

 

Will be glad for every tip i get from you guys!

 

Greetings,

Finalspace




#5161650 Explosive tangent impulses causes extreme rotation

Posted by Finalspace on 20 June 2014 - 01:26 AM

Ah i am really happy right now, now i can go to the next step, implement contact caching + warm starting, better broadphase and finally polygon bodies.

If you want to see my progress, you can check my youtube channel frequently - i upload there things i have made - but mostly in javascript tongue.png

 

Thread can be closed.




PARTNERS