He-Who-Develops-Games
Guest
|
|
« Reply #480 on: November 06, 2013, 04:09:21 PM » |
|
I just came across this in my code: you_are_a_fucking_failure = sf.Sprite(sf.Texture.from_file("awwman.png")) It's the sprite which holds the losing screen. Also, this: timeywimeywibblywobblystuff = int(sys.argv[1]) I have a penchant for silly variable names.
|
|
|
Logged
|
|
|
|
Chainsawkitten
|
|
« Reply #481 on: November 07, 2013, 06:57:03 AM » |
|
I don't think I've ever managed to write 'public' without first writing 'pubic'.
|
|
|
Logged
|
|
|
|
wbahnassi
|
|
« Reply #482 on: November 10, 2013, 07:21:06 PM » |
|
I'd assume some of the macros you're calling might use them, but you don't seem to be passing them anything that would identify the label to jump to.
Extreme pedant mode: CPP macro syntax looks like function call syntax, but you don't really call a macro, it's just a text substitution. W The only macros there are YIELD_ON, RETURN_FROM_YIELD_ON, BOOKMARK_ON and RETURN_TO_BOOKMARK_ON (special macros I wrote to do crazy stuff). Are these which you are referring to as looking like function call syntax?
|
|
« Last Edit: November 10, 2013, 07:56:47 PM by wbahnassi »
|
Logged
|
|
|
|
Geti
|
|
« Reply #483 on: November 10, 2013, 07:45:49 PM » |
|
He was referring to ThemsAllTook's slip up saying you're "calling" a macro, when macros are a preprocessor construct. I don't think I've ever managed to write 'public' without first writing 'pubic'.
I used to do this all the time when I was writing code in languages that used that keyword everywhere, now it mostly just comes after the private member declarations in any classes I write (C++) so there's not as much of a chance for that particular "lol". Similarly, I don't get to write double penetration; quite as often either due to being significantly more memory conscious - float penetration; doesn't have nearly as much oomph.
|
|
|
Logged
|
|
|
|
Will Vale
|
|
« Reply #484 on: November 11, 2013, 03:32:47 AM » |
|
Heheheh. Performance, but at a cost
|
|
|
Logged
|
|
|
|
RandyGaul
|
|
« Reply #485 on: January 16, 2014, 06:18:00 PM » |
|
what the hell am i doing return R<Component>(const_cast<Component *>(&*const_cast<R<const Component> *>(const_cast<const Component *>(this)->firstChildOfType(t).addr()))); lol Well you know, what's wrong with C style casts
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #486 on: January 17, 2014, 03:34:20 PM » |
|
You are casting *to* const Component*? That is surely unnecessary, unless you have things set up in a truly horrible way.
|
|
|
Logged
|
|
|
|
Geti
|
|
« Reply #487 on: January 18, 2014, 07:47:47 AM » |
|
Honestly I'd probably be tempted use a macro to get the computer to duplicate the code for me rather than trying to cast all the constness away, if it is indeed duplicate code. As is often the case, bad C habits die hard. I have nothing against the cast to const in that case though other than it being less than idiomatic Incidentally, I'm usually a tad annoyed when there's a base "component" class at the core of something; I feel that components should really be properly free standing and oblivious to the higher systems at play (ideally just data) rather than a glorified vtable holder indicating that the author may not really wish to move away from heirarchies at all - however that's usually 2am grumpiness talking, and I'm in the wrong room :^)
|
|
|
Logged
|
|
|
|
BorisTheBrave
|
|
« Reply #488 on: January 18, 2014, 09:39:06 AM » |
|
I mean, you've obviously given it some thought, but yes, I still think it's horrible. By all mean use a const cast to avoid duplication of methods. It's the returning different types from methods than only differ by constness that seems idiomatic. I'd just name the two methods differently rather than do that: firstChildOfType vs firstChildOfTypeRef. Which conveniently removes the need for a const cast.
|
|
|
Logged
|
|
|
|
Geti
|
|
« Reply #489 on: January 18, 2014, 02:25:10 PM » |
|
Re: your example - I'm surely missing where this calls for a base component class all I see a need for is an interface for the script components to allow them to be called, and bindings for the c++ raw components to allow them to be called from the scripts. The components otherwise could all be anything from raw structs to complicated multiple inheritance template classes, they do not need to have a common interface though unless you're forcing aspects of "parenthood" and "updating" and so on onto them, which is the place for interfaces, not a Swiss army knife base class. In games, especially component based games, we can usually find a way to be very certain about what type of object we're going to get out of any situation, and can definitely do a better solution to getting a component by name: struct Goomba { R<Sprite> graphics; R<SAT_AABB> physics; R<Script> logic; //probably shared R<Sound> squish; };
Then do your hooking stuff up as you like - however rather than someGoomba.getFirstNamed<Sprite>("graphics") you can now do someGoomba.graphics and get normal type safety stuff. For scripts to access this it does need a binding, but the binding is trivial, and you're still free to make maps of sprites, physics shapes, scripts and so on if you want to do all the attachment at runtime rather than compile time. Just my 2c on the issue, I definitely understand going the other way - however, we realised far too late with kag that our component implementation was exactly what we were warned against, and while it's possible to work around you certainly can get yourself in a jam
|
|
|
Logged
|
|
|
|
Will Vale
|
|
« Reply #490 on: February 03, 2014, 03:01:44 AM » |
|
Just chiming in that I agree with you - I'd much rather have some annoying const_casts than a duplicate method implementation for the example you showed. DRY IS ALL @Geti, I really like your simple component setup. I was going to ask what you do when a thing like "attack" hits another thing and needs to find if it has "health", but then I thought maybe that all gets taken care of in scripts? If you're not using scripted logic, I can see more need for the Entity::Component<T> style of access.
|
|
|
Logged
|
|
|
|
Geti
|
|
« Reply #491 on: February 03, 2014, 04:57:10 AM » |
|
These days I'd certainly put anything game specific (like health) in scripts, and usually have "hit" as an event that the game object can figure out what to do with. I like my game code as data for iteration speed. ...However, if you wanted to have it all in-engine and compiled for speed or some other reason you could just make sure that you actually know what you're hitting - All Goombas could have an f32 health that you'd be able to access easily ( someGoomba.health -= 0.3f;), or you could extend Script and override the interface, or you could have the Goomba implement some interface with a hit method, or just give it its own hit method if (again) you know that you're hitting Goombas. //with interface struct Goomba : public IHittable { R<Sprite> graphics; R<SAT_AABB> physics; R<Script> logic; //probably shared R<Sound> squish; //inherited virtual void hit(f32 damage, HitterType type); //for hitting f32 health; };
//without struct Goomba { R<Sprite> graphics; R<SAT_AABB> physics; R<Script> logic; //probably shared R<Sound> squish; //publicly accessible void hit(f32 damage, HitterType type); //for hitting f32 health; }; Honestly I find people often try to be way too generic with these kinds of things - for many games you could easily get away with a vector<Goomba> or Goomba* or whatever flavour of poison you prefer, no need for something as airy fairy as R<vector<R<Entity>>> with constant casting etc etc if you could have a few separate arrays of objects with specific functionality and 80% less bullshit systems around those objects. HTH, happy to discuss it more
|
|
|
Logged
|
|
|
|
coppolaemilio
|
|
« Reply #492 on: February 03, 2014, 01:25:33 PM » |
|
|
|
|
Logged
|
Sleeping at Evelend
|
|
|
|
Will Vale
|
|
« Reply #494 on: February 03, 2014, 10:50:53 PM » |
|
That's genius. Orange will never be the same again. @Geti, thanks for the perspective on how you do things. I looked through my gamecode again and it turns out that after I got the events in I was able to get rid of almost all the other->Component<T> calls. In my case the reason things are flexible/over-engineered is that I wanted to make entity description data-driven (I might've posted about this before?) because I like having all that in text files, for fast turnaround and flexibility. If I ever get around to adding scripting I may well end up in NO THE POWER land, where I can't get anything done because there are too many ways to solve a given problem Will
|
|
|
Logged
|
|
|
|
Geti
|
|
« Reply #495 on: February 04, 2014, 12:45:57 AM » |
|
I also had a giggle at the orange css shenanigans Does it make sense in context or was the site just using .orange for emphasis or something? @Will: I have nothing against flexibility, but I've seen a lot of people spend a lot of time making really "nice" entity systems rather than games, the kind of people that get games done in game jams but never actually ship anything That said, I've found scripts "as data" are actually an even better way of defining entities in a data driven way, since the script can perform smart logic to hook everything up. Consider the nontrivial case of a "worm" type enemy like in zelda where you've got a bunch of near identical "body" sprites that have to follow the "head"; if you have a config file without logic you have to define them all manually, if you have logic you can do it with a simple loop (and even set up physics constraints or other fancy shit between them at the same time). The scripts then form a sort of a constructor for the object, and eventually the game itself by allowing them to create other scripts, components, etc; you just have one hardcoded Main script that gets the ball rolling. It's taken me ages to get both comfortable and capable enough to work with this sort of free floating code and components system because I came from a very OOP background, but I'm pretty happy with it. Glad you were able to get rid of those yucky calls with a nice event system
|
|
|
Logged
|
|
|
|
bateleur
|
|
« Reply #496 on: February 04, 2014, 02:25:55 AM » |
|
I couldn't work out this morning why my code had a variable called 'roflBlock'. Surely even I wouldn't be that whimsical in my naming? After studying the corresponding code, the mystery is solved: ROFL is an acronym for "Remove Object From List".
|
|
|
Logged
|
|
|
|
Code_Assassin
|
|
« Reply #497 on: February 05, 2014, 09:57:28 AM » |
|
After studying the corresponding code, the mystery is solved: ROFL is an acronym for "Remove Object From List". Clever acronym.
|
|
|
Logged
|
|
|
|
OniWorld
|
|
« Reply #498 on: February 06, 2014, 01:50:38 AM » |
|
|
|
|
Logged
|
|
|
|
Will Vale
|
|
« Reply #499 on: February 07, 2014, 02:39:01 AM » |
|
@Will: I have nothing against flexibility, but I've seen a lot of people spend a lot of time making really "nice" entity systems rather than games, the kind of people that get games done in game jams but never actually ship anything My feeble excuse is I ship games for work, so I'm allowed to piss around overengineering stuff in my spare time Your script example is excellent, I've been doing some work extending Premake recently (so I can port things to Android, rather than writing new things worth porting - see excuse above...) and I'm getting towards the scripting epiphany. It's funny, just about my first industry job was writing the scripting language/compiler/VM for IW2, but I haven't used any scripting in my own projects. What I really appreciated at the time was how easy scripts made it to write concurrent code. Will
|
|
|
Logged
|
|
|
|
|