Jump to content

  • Log In with Google      Sign In   
  • Create Account


Member Since 15 Jun 2006
Offline Last Active Yesterday, 04:08 AM

#5013623 Feasibility of writing android apps purely through the NDK

Posted by Katie on 23 December 2012 - 03:48 AM

I did some work in this area; I don't think there would be major problems. The annoyance is that it's not just a single line of Java you need to write -- basically any event you actually want to use (screen touches, rotations, anything like that) requires a thunk to pass it into your NDK. On the plus side, once done, done.


You'll also need to think about whether you'll need to leave C++ and go back to Java to do things (to access other features on the phone). If you want to write something that uses screen taps and draws things, the work is pretty simple. If you want to start talking to servers, do GPS or use the camera or things like that then it gets complicated fast.


You can do this transition into C++ at any layer BTW -- you could do game logic in Java and the rendering in C++. It's just a call into a shared object -- a DLL.


Why did I do it? Simply because I'm more productive in C++ because I'm more familiar with it. If you're starting from scratch, you may be better off choosing the path of lesser resistance and working in Java.

#5013465 Preventing Out-Door dust particles from entering inside buildings

Posted by Katie on 22 December 2012 - 12:47 PM



It's always easier to cheat. You're trying to solve slightly the wrong problem; You're trying to figure out how to run a system where you make random rain and then work out how to not have it enter the buildings.


It's much easier to do this in your level design. Make it "rain" in boxes. The raindrops start at the top and fall down (you can do this in the vertex shaders fairly easily). When they get to the bottom of the box they get recycled at the top.


You plonk these down in your level... at ground level in the streets, at roof level over the buildings. You should also then be able to cull them fast -- if the view is indoors, it can't see up anyway, so the overhead rainboxes are never rendered. (You can get away with the rain sequence repeating as well. You can also get away with using the same rain positions for all the boxes... add some distance fogging and no-one will ever spot the rain tiling :-)


Likewise your dust -- it lives in boxes. The player moves through the box, dust is generated, it drifts back down.. job done. The dust is never made where there isn't a box -- like inside.


The goal of games development is to make something that's real enough that if the player co-operates with suspension of disbelief looks right. It doesn't actually have to solve all the annoying things for real if you can cheat...

#5011380 Is there an AI that alters program code?

Posted by Katie on 16 December 2012 - 04:34 PM

The Tierra project? http://life.ou.edu/tierra/

#5007926 Class Structure for a Text Adventure Game

Posted by Katie on 06 December 2012 - 05:31 PM

"bool playerHas"

You'll be back here asking how you have other characters carry things...

There are a couple of reasonable approaches. One is to have a true tree structure where objects can contain/consist or otherwise relate to other objects; rooms are objects which contain items and characters, characters can "hold" or "wear" objects, which in turn can contain other objects.

Lets you handle "examine gun in pocket of coat"

A simpler, but still useful mechanism, much used in games in the 8 and 16 bit eras is to give each object a "location" field which is an integer. If it's positive, the object is present in that numbered location. If it's negative, the object is being carried by character number abs(location). Location zero doesn't exist, so objects can be removed from the game world. Other location numbers can be "special" in various ways.

It then gets reasonably easy to implement "give" and "take" and then you can have puzzles where you need to stun the guard to take his sword (because when he's unconscious he doesn't attack you if you try to take objects off him) and use it to cut the rope...

"bool inspectable"

Just give each item a map of properties, string->string. When a player runs "Examine X", you can check X to see if it has a "examine" property. Otherwise it's "nothing special".

You can then encode several other useful things. If the item has "get_message" you can't get the item, but the string is the message to print instead. If the item has a "text" property, then "Read X" works on it... and so on.

That's how you make the door -- it has a "get_message". Now that the door is an object, handling "Use key on door" is easy. It's a special case of "Use X on Y"...

Back in the 8/16bit days, you'd have a single routine for each verb. The routine would check the objects. So first off you check if the objects are "present" (held by the player or in the current location) and then you do; if ob1 = key and ob2 = door then unlock_door()

Unlock_door() would clear the "blocked" bit in that link and swap the "locked door" object for the "opened door" object. (by swapping their locations).

These days, if your language supports them, you may want a set of maps which map tuples of (verb_number, object) -> function and (verbnumber, obj, preposition, obj) -> function

#4998935 The Singleton Pattern: To be or not to be [used]?

Posted by Katie on 08 November 2012 - 11:24 AM

How about we stop having this argument, because it always ends up with a bunch of perfectionist architects stating categorically no to it and a bunch of practical implementationists saying; the goal here is to write functioning code and anything that makes that happen is OK. And the two are never going to see eye to eye and this topic is boring after about the sixth time around.

#4996897 linux ncurses

Posted by Katie on 03 November 2012 - 10:49 AM

Please don't do this. You're about to get sucked into a disaster of tears and pain.

"i want to program at the OS level in linux"

No you don't. Really, really, really, you don't. The only people who do this are people who are working on the OS. Everyone else uses the abstraction layers so they don't go insane and they do actually get some work done.

ncurses is good enough for people who implement shells, terminal media players, rogue-likes, interactive fiction games, tetris clones and a hundred others. It means their software runs reliably on thousands of configurations. It has had decades of development and debugging work by hundreds if not thousands of people.

Why would you give up all that? Because you imagine a performance gain? Painting a 1000 character display? Every screen refresh perhaps? On modern machines which are quite capable of repainting million-pixel displays at 50 or 60hz?

Why is this place so full of people who want to spend their time re-implementing these sorts of layers? Is it really just misguided masochism? Why do people want to faff about doing things like this instead of writing actual games?

#4996136 How does OpenGL use its enum values?

Posted by Katie on 01 November 2012 - 04:33 AM

Inside the driver, the code paths tend to be convoluted and so there really are a lot of "if (X) { callASetupFunction(); }" type structures. And, yes, that does mean there's a lot of testing needed to exercise all the sections -- and a lot of bugfixing about edge cases; "When I select X Y and Z, W doesn't work..."

#4994654 Questions about AI

Posted by Katie on 28 October 2012 - 02:35 AM

"I thought of passing a pointer of the room to the object, but that sound's like it can get messy because of the circular dependency."

It's not a 'circular dependency', it's a circular reference. Pointers can but do not necessarily convey memory ownership.

It's fairly typical in these sorts of games that the objects know which room structure they belong to and the room has references to all the objects contained in it. The room comes with nice utility functions such as "iterate over all contents except object X" or "iterate over all contents except the ones in this list" or "iterate over all the contents whose ID exceeds N" so that an object can cause things to happen to other objects more easily. Also you're going to have finder methods; "Find me all the objects which are touching object A". "Iterate over all objects within R of X,Y".

A circular dependency would imply that you're expect the room to delete the objects in it when they're not needed (probably the case) and also that the objects are expecting to delete the room they're in for some reason (which would be nuts. Not least because many objects would delete the room several times).

The directed and necessarily acyclic graph of memory ownership is not the same as the possibly cyclical graph of object references.

#4992568 Do you need a company for you're first game launch?

Posted by Katie on 21 October 2012 - 03:19 PM

No, you don't need a company yet. Don't worry about stuff like this. If you finish your game, there'll be loads of time to sort this out then. Write code, sort out other problems later.

#4992529 Seeking resume advice

Posted by Katie on 21 October 2012 - 01:41 PM

"as this is only a résumé I think I'd wander into CV territory if I did that."

Look, I know people keep telling you these sorts of things, I have no idea where this idea started that boring CVs are good, but it needs stopping very quickly. Seriously -- there have been days where I'd rather not hire ANYONE and do the work myself on the weekends than have to go through another pile of turgid lists-of-jobs-that-people-once-had.

It's not "a CV" or "a resume". It's a SALES PITCH. It's the only one you get. It's standing between you and the bin. You've got about 3 minutes before I'm interrupted by something to convince me to spend a whole couple of valuable hours talking to you. A list of jobs you once had doesn't make you stand out. Like I say, everyone has a CV like that.

Eventually someone will bully me into making a decision about who gets interview slots, and given a pile of CVs all of equal boritude I pick a couple off the stack of ones which at least feature the right skills and go "Oh, look, those ones, go away". Basically your chances of getting an interview are based on whether you're on the top or the bottom of the pile of junk on my desk. I love the rare occasion when I get a CV where I immediately say "we'll talk to this person" and the decision doesn't have to be a painful one. I mean, how else am I supposed to tell otherwise? I've got a dozen CVs of people who say they did 4 years C++ at XYZ Ltd (who I've not heard of) on a project I've not heard of and whose value or success or failure is unstated. And then all of those people followed it up with 2 years of C++ at ABC Enterprises (who I've not heard of) on a project I've not heard of and whose value or success or failure is unknown...

I don't know why you're listening to this rumour that's doing the rounds that boring is better when someone who hires software engineers is begging you to stand out from the crowd and sell yourself.

#4991870 Is it acceptable to call a destructor?

Posted by Katie on 19 October 2012 - 01:12 PM

At the level you're working at, you do not call destructors.

Normally people do not call the destructors. Since C++ is clearly pretty new to you, take the advice and do what everyone else does and don't call the destructors directly. Because if you do, you'll be back here in a week asking people to debug the weird crashes in your program and that road is going to be really hard work because suddenly you're in a place where very few people will be able to help you because everyone else doesn't call the destructors because they don't want to be in that place.

There is a reason people learning to juggle start with bean bags and not running chainsaws. It's less exciting, that's for sure. But it's also less exciting.

#4991849 What to know in order to write a mesh parser?

Posted by Katie on 19 October 2012 - 12:08 PM

People don't do this. Work out what you need from your mesh data. Design a file format to hold it. It can be in denormalised formats, laid out in a nice easy to handle way for your renderer.

You then do one of two things -- you write an exporter from something like Blender which saves to your files. Or you write a translator which goes from a well known file format into your file format. Which can be quick, hacky and written in something like Perl or Python.

#4986700 Efficient GUI clipping on the GPU

Posted by Katie on 04 October 2012 - 03:23 AM

You may be solving the wrong problem.

Generally, UI code solves this problem by just drawing the windows in order, front to back (omitting only completely obscured windows). Why? Because that's actually faster than faffing about...

Yes, it generates some overdraw, but that's still usually easier than trying to clip -- UI pixels are often fairly cheap (being things like flat or shade fills of rectangles).

If you're actually running this on a 3D card, then the obvious answer is just to use the Z buffer to sort this problem out for you. Which would be the second approach I'd try, but only if the overdrawing method proved slow.

Go for the simplest approach until you really find it won't work.

#4985489 Class to store different uniforms (variant like)

Posted by Katie on 30 September 2012 - 03:18 PM

OK, so the usual trick about storing different types in a map is to go at it like this;

You create an envelope class which implements your interface and in turn delegates the work to an interface pointer. You create a suitable templated class into that interface pointer.

Like this;

class Inner
  virtual void doStuff(<params>)=0;
  virtual Inner *cloneAt(void *address)=0;

template<class DATA>
class InnerTempl
  DATA data;
  virtual void doStuff(<params>) { // in here you can use 'data' to work on it, and it has the right type. }

  InnerTempl(const DATA &d):data(d) {}
  virtual Inner *cloneAt(void *address)
     return new(address) InnerTempl(data);

class Outer
  Inner *pInner;
  void doStuff(<params>) { pInner->doStuff(<params>); }

  template <class X> assign(const X &x) { pInner=new InnerTempl<X>(x); }

So far, so good.

You can store Outers in a map. There's some issues about memory management and you'll need to flesh those out into real classes.

Avoiding the memory management can be done reasonably neatly if you're careful.
Start with this;

class Outer
  Inner *pInner;
  unsigned char space[32]; // you'll need to pick a size here that's big enough for your purposes.
  void doStuff(<params>) { pInner->doStuff(<params>); }
  template <class X> assign(const X &x) { pInner=new(space) InnerTempl<X>(x); } 
  template <class X> operator=(const X &x) { pInner=new(space) InnerTempl<X>(x); }

Now you don't need a separate inner object, so there's one less memory alloc and no loose pointers. It's a bit hacky and relies on picking a size that's 'big enough' but games development is ~1% genius and 99% hacking that genius to work practically.

STL mandates objects in maps must be copyable. And this then, is why we implemented cloneAt. Note that it needs the virtual dispatching to end up in a function which knows what type DATA really is.

Add to Outer an assignment operator.

Outer &operator=(const Outer &other) { pInner = other.pInner->cloneAt(space); }

Likewise, implement a copy constructor.

STL mandates objects in maps must have a null constructor. Make it have a null pInner to start with & add all the exception handling to cope with that and you're done.

Now you can store arbitrary types in the map by just assigning to them and iterate through them calling doStuff() on each one.

typedef map<string,Outer> MYMAP;
MYMAP mymap;

Job done.

Then in this case, doStuff() probably takes an integer slot and then calls an overloaded glUniform() function passing "data" in.

Mine looks like this;

void glUniform(int slot,int value)		  { glUniform1i (slot,value);}
void glUniform(int slot,unsigned int value) { glUniform1i (slot,value);}
void glUniform(int slot,float value)	    { glUniform1f (slot,value);}
void glUniform(int slot,const vec2 &value)  {glUniform2fv(slot,1,value.ptr());}
void glUniform(int slot,const vec3 &value)  { glUniform3fv(slot,1,value.ptr());}
void glUniform(int slot,const vec4 &value)  { glUniform4fv(slot,1,value.ptr());}
void glUniform(int slot,const ivec2 &value) { glUniform2iv(slot,1,value.ptr());}
void glUniform(int slot,const ivec3 &value) { glUniform3iv(slot,1,value.ptr());}
void glUniform(int slot,const ivec4 &value) { glUniform4iv(slot,1,value.ptr());}
void glUniform(int slot,const matrix &value){ glUniformMatrix4fv(slot,1,GL_FALSE,value.ptr());}

// I have my CPU vector classes named to match the GLSL ones because I got bored of accidentally using the wrong ones all the time.
// generally ptr() gets a base pointer to real data in the classes.

#4984878 Class to store different uniforms (variant like)

Posted by Katie on 28 September 2012 - 04:02 PM

The trick with stuff like this is to first off, write a bunch of overloaded version of glUniformXYZ() which takes C++ types and a slot and sets the uniform.

Then you can write templated setter classes which you can store in the map.

Then you can write a simple interface to the uniforms map which takes a string and an arbitrary type and puts a setter into the map.

Then you just iterate over the map calling the setter through an interface.

If you do this neatly, BTW, you can arrange to store either a value or a reference into the map. So you can express "Set this uniform to integer 7, but set that one to the value of this integer over here" in the same uniforms group.

If you make the setters a PIMPL interface with a templated inner class constructed inplace into a convenient array of spare memory and set up copy operators properly, then the setters are plain value objects and hence can be stored directly in the map. All this avoids nasty casts and will properly type-check things at compile time. (Because if you try and store an X and there ultimately isn't a suitable glUniformXYZ then the code won't build). And you can hotwire it to use your own vector/matrix classes and write them into the GLSL versions.

I've probably got some code somewhere if that doesn't make sense.