Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1393497 Posts in 67076 Topics- by 60009 Members - Latest Member: amandaparsons

July 24, 2021, 12:57:15 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)What are you programming RIGHT NOW?
Pages: 1 [2] 3 4 ... 71
Print
Author Topic: What are you programming RIGHT NOW?  (Read 176481 times)
Triplefox
Level 9
****



View Profile WWW
« Reply #20 on: January 24, 2011, 02:21:47 AM »

I decided that my game needs some AABB, Euler-integrated collision now, after going for a while as just a tile-pathfinder. Fortunately I have some primordial collision ooze in the form of a hierarchical AABB coordinate system, which currently runs the camera and sprite positioning; it was actually the first thing I developed for this project, before any game was designed.

The impetus for the collision is thus: I started off with my pathfinding using linear, time-based tweening. However, it gets finicky to make tweens behave well(no pausing, jittering, or jumping) when you send things on a new path midstream, wheras if I follow paths by setting velocity and direction I only really have to worry about overshoots. And if it were just that I would figure something out regardless....however, I'm also going to use the collision later to do some entity-to-entity checks - projectiles and such. Make battles more kinetic. So I might as well do it now and transition to a velocity-based system.

Basically, a world consists of maps which in turn have width*height references into common rooms (screen-sized chunks of map which are packed in simple ways -- a mix of uncompressed, RLE, and LZ-style), 4 palette references, tileset references (which are contain 64 tiles that each contain 4 8x8 subpatterns), and pattern references (which basically state which CHR banks to use). I will likely waste 1K of RAM on screen buffer (buffer for 4 rooms, each room is 256 bytes uncompressed), and decode rooms in chunks as they're scrolled into.

This is a pretty classic method, though everyone seems to have their own variation on the theme. I know for a fact Metroid uses similar techniques, and Ultima 7 as well(on a much grander scale, being made for 1992 DOS systems). Both have some reverse-engineered documentation somewhere online.
Logged

Glaiel-Gamer
Guest
« Reply #21 on: January 24, 2011, 07:41:42 PM »

fast sin / fast cos functions using lookup tables. Tables have 256 entries and periodicity is handled 100% by integer wraparound
Code:
inline float sin(float x){
    x = x/(2.0*3.1415926535897932384626433832795028841971)*256.0;
    unsigned char index0 = x;
    unsigned char index1 = x+1;
    float fpart = x-int(x);
    return sin_table[index0]*(1.0-fpart)+sin_table[index1]*fpart;
  }
  inline float cos(float x){
    x = x/(2.0*3.1415926535897932384626433832795028841971)*256.0;
    unsigned char index0 = x;
    unsigned char index1 = x+1;
    float fpart = x-int(x);
    return cos_table[index0]*(1.0-fpart)+cos_table[index1]*fpart;
  }


quite a bit faster than built-in on the console


gla::sin Time: 2321ms
std::sin Time: 17775ms

for 20000000 iterations


small change makes it even more efficient (1392ms) (only showing sin cause cos is pretty much the same)
Code:
inline float sin(float x){
    x = x/(2.0f*3.1415926535897932384626433832795028841971f)*256.0f;
    int X = x;
    unsigned char index0 = X;
    unsigned char index1 = X+1;
    float fpart = x-X;
    return sin_table[index0]*(1.0f-fpart)+sin_table[index1]*fpart;
  }
(yes these profiling tests are with optimization on)



table generation:
Code:
void gla::sincos_init(){
  for(int i = 0; i<256; i++){
    sin_table[i] = std::sin((float(i)/256.0)*2.0*3.1415926535897932384626433832795028841971);
    cos_table[i] = std::cos((float(i)/256.0)*2.0*3.1415926535897932384626433832795028841971);
  }
}


also allows for an efficient combo sincos function
Code:
inline void sincos(float x, float& s, float& c){
    x = x/(2.0f*3.1415926535897932384626433832795028841971f)*256.0f;
    int X = x;
    unsigned char index0 = X;
    unsigned char index1 = X+1;
    float fpart = x-X;

    s=sin_table[index0]*(1.0f-fpart)+sin_table[index1]*fpart;
    c=cos_table[index0]*(1.0f-fpart)+cos_table[index1]*fpart;
  }
« Last Edit: January 24, 2011, 07:55:54 PM by Glaiel-Gamer » Logged
BlueSweatshirt
Level 10
*****

the void


View Profile WWW
« Reply #22 on: January 24, 2011, 08:50:19 PM »

You rock.  Kiss


For operations that are complex, but not necessarily needing perfect accuracy, this is a godsend for speed.
Logged

Glaiel-Gamer
Guest
« Reply #23 on: January 24, 2011, 10:07:03 PM »

You rock.  Kiss


For operations that are complex, but not necessarily needing perfect accuracy, this is a godsend for speed.

i'm pretty sure i can get it faster too, but i've checked out of the office for the day so i'll finish it up tomorrow

(on pc its only about 3x faster than std::sin rather than >10x faster too)
Logged
eclectocrat
Level 5
*****


Most of your personality is unconscious.


View Profile
« Reply #24 on: January 24, 2011, 10:53:54 PM »

Vector graphics compositor in C++ with a Lua binding + some Lua GUI classes to test it out.
Logged

I make Mysterious Castle, a Tactics-Roguelike
FrostedSentry
Level 0
***


View Profile WWW
« Reply #25 on: January 25, 2011, 11:05:40 AM »

For today... Implement part of stage 2 which requires making a net that butterflies get stuck to. I'll need to write something that detects a swipe near the net so the player can keep the butterflies away from it. If too many get stuck to the net, it'll be hard for the player to progress.
Logged

David McGraw ∴ Twitter
SFBTom
Level 1
*



View Profile WWW
« Reply #26 on: January 25, 2011, 11:49:32 AM »

Just finished up a tool for quickly and visually defining interactive areas in my iPhone adventure game. Written in flash, spits out plists. Did I mention how horribly verbose the plist format is?
Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #27 on: January 25, 2011, 12:09:27 PM »

fast sin / fast cos functions using lookup tables.
Though I think rewriting sin/cos is basically pointless, I note you can cut out a few arithmetic operations using a second table:
return sin_table1[index0]+sin_table2[index0]*fpart;

You should also post the maximal inaccuracy that your function reaches, otherwise it cannot be compared to other implementations.

Also note that using arrays slightly increases memory pressure, so can slow down the rest of your program fractionally.
Logged
Glaiel-Gamer
Guest
« Reply #28 on: January 25, 2011, 12:26:37 PM »

fast sin / fast cos functions using lookup tables.
Though I think rewriting sin/cos is basically pointless

std::sin was taking up 10-17% of my time on the console when i profiled it


(using my sin/cos improves FPS by 2-4 on my overload test level on pc (from 20-21fps to 23-24fps))
Logged
Klaim
Level 10
*****



View Profile WWW
« Reply #29 on: January 25, 2011, 01:03:51 PM »

I'm finishing a Python script that uses a code generator that takes an XSD file and generate the corresponding C++ architecture.

It's not for a game.
If I finish that tonight I'll get back to my game's code.
Logged

FrostedSentry
Level 0
***


View Profile WWW
« Reply #30 on: January 26, 2011, 01:37:17 AM »

cool, finished up half of the stage 2 implementation... also took a sec to add chat functionality to the webpage... figured it'd be nice to be a little more customer facing. rack ops time!
Logged

David McGraw ∴ Twitter
st33d
Guest
« Reply #31 on: January 26, 2011, 06:21:12 AM »

Putting in the help animations and tutorial.

Bar assembling all the levels into a campaign, I am right at the very end of 8 months of work.

This is my theme tune at the moment: http://listen.grooveshark.com/s/Dream+Is+Collapsing/2WYvo2
Logged
FrostedSentry
Level 0
***


View Profile WWW
« Reply #32 on: January 26, 2011, 11:21:29 AM »

Coffee
Logged

David McGraw ∴ Twitter
Ivan
Owl Country
Level 10
*


alright, let's see what we can see


View Profile
« Reply #33 on: January 26, 2011, 02:03:25 PM »

swords slicing through polygons like soft butter
Logged

http://polycode.org/ - Free, cross-platform, open-source engine.
st33d
Guest
« Reply #34 on: January 26, 2011, 02:43:48 PM »

polyunsaturated?
Logged
bengrue
Level 0
***


I code. A lot.


View Profile WWW
« Reply #35 on: January 27, 2011, 02:35:30 AM »

Right now I'm implementing some cutscenes in a javascript jRPG enginey thing, and contemplating a DSL for the problem after using too many onCompletes.
Logged

Current Project: Sully: A Very Serious RPG

Executive Producer of Dungeons of Dredmor

@bengrue on the twitternets
Mstrp
Level 0
**


View Profile
« Reply #36 on: January 27, 2011, 08:44:58 AM »

Working on my Versus entry, recently finished a quadtree implementation on the server. Next up, unit abilities with some sort of buff/debuff tracking system. Never done anything like it before, looking forward to it.
Logged
Glaiel-Gamer
Guest
« Reply #37 on: January 27, 2011, 11:03:19 AM »

writing a std::list implemented as a deque to reduce memory allocations and improve locality of reference

here we are (it compiles and my game doesn't crash, which is good enough for now, notice any glaring errors?)
Code:
#ifndef GLA_PAGEDLIST_H
#define GLA_PAGEDLIST_H


#include <cstring>
#include <cstdlib>
#include "podvector.h"


namespace gla {
  template <typename T>
  class pagedlist {         //std::list implemented as a queue
    private:
      struct node {
        node* next; //if node is allocated, this points to the next one in the list
                    //if node isn't allocated, this points to the next free node in the list
        node* prev; //prev only applicable for allocated nodes
        //T data;

        char data[sizeof(T)]; //bytes for actual class data

      };
      struct page {
        page* next;
        gla::podvector<node> nodes;
        page(int size_):next(NULL),nodes(size_){}
      };
      page memory;
      node begin_;
      node end_;
      node* freelist;
      int size_;

      void addToFreeList(node& n){
        n.next = freelist;
        freelist = &n;
      }
      void page_init(page& mem){
        for(int i = 0; i<mem.nodes.size(); i++){
          addToFreeList(mem.nodes[i]);
        }
        mem.next = NULL;
      }
      node* alloc_node(){
        if(freelist == NULL){
          page* nextpage = &memory;
          while(nextpage->next) nextpage = nextpage->next;
          nextpage->next = new page(nextpage->nodes.size()*2);
          page_init(*(nextpage->next));
        }
        node* n = freelist;
        freelist = freelist->next;
        return n;
      }
      void freepage(page& mem){
        if(mem.next){
          freepage(*mem.next);
          delete mem.next;
        }
      }
    public:

      class iterator {
        friend class pagedlist<T>;
        private:
          node* n;
        public:
          iterator(node* n_=NULL):n(n_){}
          bool operator==(const iterator& rhs){return n==rhs.n;}
          bool operator!=(const iterator& rhs){return n!=rhs.n;}
          iterator operator++(){n=n->next;return *this;}                //preincrement
          iterator operator++(int){n=n->next;return iterator(n->prev);} //postincrement
          iterator operator--(){n=n->prev;return *this;}                //preincrement
          iterator operator--(int){n=n->prev;return iterator(n->next);} //postincrement
          T& operator*(){return *reinterpret_cast<T*>(n->data);}
          T* operator->(){return reinterpret_cast<T*>(n->data);}
      };


      pagedlist(int initial_page_size=8): memory(initial_page_size) {
        freelist = NULL;
        page_init(memory);
        begin_.next = &end_;
        begin_.prev = NULL;
        end_.prev = &begin_;
        end_.next = NULL;
        size_ = 0;
      }

      pagedlist(const pagedlist<T>& rhs): memory((8>rhs.size())?8:rhs.size()) {
        size_ = 0;
        freelist = NULL;
        page_init(memory);
        begin_.next = &end_;
        begin_.prev = NULL;
        end_.prev = &begin_;
        end_.next = NULL;

        node* n = rhs.begin_.next;
        while(n != &rhs.end_){
          push_back(*reinterpret_cast<T*>(n->data));
          n = n->next;
        }
      }

      pagedlist<T> operator=(const pagedlist<T>& rhs) {
        if(&rhs != this){
          clear();
          node* n = rhs.begin_.next;
          while(n != &rhs.end_){
            push_back(*reinterpret_cast<T*>(n->data));
            n = n->next;
          }
        }
        return *this;
      }


      void clear(){
        node* n = begin_.next;
        while(n != &end_){
          reinterpret_cast<T*>(n->data)->~T();
          n = n->next;
        }

        end_.prev->next = freelist;
        freelist = begin_.next;

        begin_.next = &end_;
        begin_.prev = NULL;
        end_.prev = &begin_;
        end_.next = NULL;

        size_ = 0;
      }

      ~pagedlist(){
        clear();
        freepage(memory);
      }

      void push_front(const T& data){
        node*n = alloc_node();

        n->prev = &begin_;
        n->next = begin_.next;
        begin_.next->prev = n;
        begin_.next = n;

        /**reinterpret_cast<T*>(n->data) = */new (n->data) T(data);
        size_++;
      }
      void push_back(const T& data){
        node*n = alloc_node();

        n->prev = end_.prev;
        n->next = &end_;
        end_.prev->next = n;
        end_.prev = n;

        /**reinterpret_cast<T*>(n->data) = */new (n->data) T(data);
        size_++;
      }

      void pop_back(){
        node* newend = end_.prev->prev;
        newend->next = &end_;

        reinterpret_cast<T*>(end_.prev->data)->~T();

        addToFreeList(*end_.prev);
        end_.prev = newend;
        size_--;
      }

      void insert(iterator pos, const T& value){
        node* posn = pos.n;
        node* prev = pos.n->prev;
        node* n = alloc_node();

        posn->prev = n;
        n->next = posn;
        n->prev = prev;
        prev->next = n;

        /**reinterpret_cast<T*>(n->data) = */new (n->data) T(value);


        size_++;
      }

      iterator erase(iterator pos){
        node* prev = pos.n->prev;
        node* next = pos.n->next;
        prev->next = next;
        next->prev = prev;

        reinterpret_cast<T*>(pos.n->data)->~T();
        addToFreeList(*pos.n);


        size_--;
        return iterator(next);
       
      }

      iterator begin() { return iterator(begin_.next); }
      iterator end() {return iterator(&end_); }

      T& back(){
        return *reinterpret_cast<T*>(end_.prev->data);
      }

     

      int size() const {
        return size_;
      }

      template <class Predicate>
      void remove_if(Predicate pred){
        iterator it = begin();
        while(it != end()){
          if(pred(*it)){
            it = erase(it);
          } else {
            ++it;
          }
        }
      }
  };
}



#endif

I only implemented functions my game uses so its only a partial implementation of std::list, but it will help keep list nodes mostly on the same page in memory
« Last Edit: January 27, 2011, 03:46:04 PM by Glaiel-Gamer » Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #38 on: January 28, 2011, 04:38:21 PM »

No bugs, but a few nitpicks on performance and style:

It seems pretty similar to allocating your memory in slabs - it wouldn't be quite the same, but you could simply use the built in allocator support to do so.

node::data doesn't have the same alignment requirements as T does. Unlikely to go wrong, though.

freepage is recursive for some reason.

You never free pages except at the end. This would be ok, if it wasn't you are also doing exponential growth of page sizes. Those smaller pages are going to be a constant thorn in your locality problems, you really want it so that long term use with a bounded size eventually ends up on one page. You should at least free all but the largest page when clearing.

Potentially, large pages could be aligned on actual memory pages. I think this has some performance benefits.

You can use a raw pointer to an array instead of a vector, as you are not using nodes.size() anywhere, and save yourself a couple of bytes. For that matter, you should allocate page and the associated node list consecutively, this would avoid an additional allocation.

Default constructor does allocations - this should be avoided, as it's often unavoidable to default construct things when writing templated algorithms.

You use const T& when sometimes T would be more appropriate for some T. Type-trait that stuff.
Logged
Glaiel-Gamer
Guest
« Reply #39 on: January 28, 2011, 05:12:49 PM »

You never free pages except at the end. This would be ok, if it wasn't you are also doing exponential growth of page sizes. Those smaller pages are going to be a constant thorn in your locality problems, you really want it so that long term use with a bounded size eventually ends up on one page. You should at least free all but the largest page when clearing.

Potentially, large pages could be aligned on actual memory pages. I think this has some performance benefits.

You can use a raw pointer to an array instead of a vector, as you are not using nodes.size() anywhere, and save yourself a couple of bytes. For that matter, you should allocate page and the associated node list consecutively, this would avoid an additional allocation.

thanks for the pointers, as I said before this is meant to be specific to my game (most of the commonly-accessed lists are copy-constructed from level data which avoids the small-page problem) but I'll check these out at least.
Logged
Pages: 1 [2] 3 4 ... 71
Print
Jump to:  

Theme orange-lt created by panic