Bay 12 Games Forum

Please login or register.

Login with username, password and session length
Advanced search  
Pages: 1 ... 704 705 [706] 707 708 ... 796

Author Topic: if self.isCoder(): post() #Programming Thread  (Read 890081 times)

Parsely

  • Bay Watcher
    • View Profile
    • My games!
Re: if self.isCoder(): post() #Programming Thread
« Reply #10575 on: June 01, 2017, 05:07:23 pm »

Can we use this thread to talk about stuff we're doing we think is cool?
Spoiler: if not I'll spoiler it (click to show/hide)
Dude, this is fucking awesome.
Logged

flabort

  • Bay Watcher
  • Still a demilich, despite the 4e and 5e nerfs
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10576 on: June 01, 2017, 05:44:08 pm »

So I have a google doc. I'm extracting dates from forum pages by XML - some of you may remember this from 3 years ago.
I found a much better way of extracting the date and time, I get the printed page for URL and my formula looks like this: "=IMPORTXML($H$1,CONCATENATE("//dt[@class='postheader'][",C4,"]/strong[3]/text()"))" (where H1 is the forum page, like http://www.bay12forums.com/smf/index.php?action=printpage;topic=98412.0 , and C4 is the post number and this forumla is in F4).

The dates look like this: May 24, 2017, 11:56:16 pm
Now, I want to convert this to a date readable by numeric formulas. EG "=now()-F4", but neither Datevalue() or timevalue() can read it.
Logged
The Cyan Menace

Went away for a while, came back, went away for a while, and back for now.

Culise

  • Bay Watcher
  • General Nuisance
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10577 on: June 06, 2017, 04:05:36 am »

Sounds like you're going to have to chop it up and construct your date and time manually.  In Google Docs, and it sounds like this is in its Excel-analogue, DATEVALUE and TIMEVALUE won't work on the whole, but I just ran a quick test and they'll work on their appropriate component halves.  Moreover, due to how Excel constructs date and time-formatted serial numbers (to wit, the former as integers and the latter as fractional values), you can then simply add these back together and get a nice convenient datetime-formatted serial number. 

So, for your case where the date string of the format cited is in F4, what you want should be something like...
Code: [Select]
=DATEVALUE(LEFT(F4,FIND(",",F4,FIND(",",F4)+1)-1))+TIMEVALUE(RIGHT(F4,LEN(F4)-FIND(",",F4,FIND(",",F4)+1)-1))This spits out a lovely Excel-formatted standard datetime number, nearly guaranteed to be unreadable to human eyes unless parsed through Excel's (or Google Docs') cell formatting, and just-as-guaranteed to work quite nicely with any other date-time functions such as NOW(), TODAY(), or DATEDIF().  Since it's a big ol' blob of text right there, here's how it breaks down, just because I'm in a bit of odd, verbose mood at 3 AM and not because I think you actually need it this done so granularly.  I mean, you're working with XML and XPath queries, so you almost certainly know all of this part already; this is more because I'm in schoolteacher mode and can't leave it as just that. :P
Spoiler (click to show/hide)
« Last Edit: June 06, 2017, 04:19:16 am by Culise »
Logged

DeKaFu

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10578 on: June 07, 2017, 12:46:01 pm »

So... Still a relative beginner here. I guess I have a design question, about creating a system for rendering sprites in C++. I've been fruitlessly thinking in circles for the past few days, so maybe an outside perspective would help.

My situation is that I have a nicely working program that runs in the console. It has a class representing the main objects of interest (let's call them Things), which have complex rules for initializing themselves with various randomized stats, and are pretty much self-contained. I also have functions for creating Things on a vector, renaming them, and creating new Things based on existing Things. Currently accessed through a shitty text-based console interface in main.

So now, the next step is that I want to create a simple graphical visualizer that lets me view each of my Things one at a time, and ideally also create a GUI that lets you access the same functions as my text interface. I'm learning/using SDL2, and feel like I grasp the main points of getting pictures on the screen. I'm realizing the actual GUI part is going to be pretty complicated, but I'm not even worrying about that yet... for now it's the overall design of the sprite rendering system that's leaving me feeling a bit helpless.

See, I really like the idea of NOT mingling any SDL code with my Thing code. What if I decide to swap out to a totally different graphics system later? But a lot of tutorials seem to do things like store pointers to a critter's texture within the critter's class itself, or give the class a "texture" object holding the texture-pointer that knows how to draw itself. That feels iffy to me... In an ideal world, I think I'd prefer my Things to continue to operate in a way that wouldn't be harmed by ripping the entire graphics system out. Is that stupid?  :-\

I understand that a way some people do it is to have the "Thing" not know anything more than an identifier for its sprite, and have a "TextureRenderer" object that can take that information and use it plus the SDL renderer/functions to draw things. But there's a lot of big gaps in my understanding of how exactly that works... what gets sent where and how, mostly. Does the Thing still ask to be drawn itself, somehow? (Like Thing1.drawsprite()?) Do you ask the TextureRenderer to draw it? (TextureRenderer.draw(Thing1.sprite)?) Some kind of intermediate function or object? (DrawThinger(Thing1.sprite, TextureRenderer)?) What data is being passed where in each case? I've been googling about it for days and still don't fully understand how to apply it...

Just to make things more Fun and complicated, there's no single "Thing" sprite I can just plug in... Instead, each Thing has a set of stats representing appearance that are randomly generated when it's created. So drawing a thing actually involves layering several semitransparent textures (chosen from a list of possibilities) together, and there's no way to know which textures a given Thing will need until it's created at runtime, only the list of all possibilities. In fact, each Thing will eventually need multiple "layered sprites" based on their set of stats corresponding to different "views" (front, back, etc.).
I guess ideally the Renderer doesn't have to know any of that and only receives/parses requests to draw a given texture in a given place... Is that unrealistic, though? I still can't quite picture how it would work.

I guess the TLDR is:
1. Is it possible/desirable to make a system for drawing data-only game entities where the entities are totally ignorant of the drawing system?
2. If so, how do you get the necessary information sent between them?
3. Does it all fall apart with my layered-sprite requirement, where you need instance-specific data from the entity to know which textures to draw?

I'm hoping to expand it later into something resembling a full, menu-based game (with game states, etc) so I don't want to inadvertently sabotage myself this early in the process...

Logged

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10579 on: June 07, 2017, 02:47:57 pm »

Quote
I'm currently coding in ye olde C++, but I'm both intrigued and intimidated by C++11 and its fancy features like built-in smart pointer types. Considering SDL is basically in C, it has a lot of raw pointers hanging around everywhere... Part of me likes the idea of wrapping it all up in unique_ptrs and shared_ptrs to make pointer/memory management safer, but it seems like it'll also add another layer of complexity to worry about while I'm still struggling to wrap my head around more basic stuff. I'm having a lot of trouble deciding whether or not now is the time to take the plunge... Anyone have any opinions?

I I remember correctly, then a lot of the SDL pointers need to be freed with SDL methods. So you gotta give the smart pointers you make a custom deleter. Should probably look something like
Code: [Select]
std::shared_ptr<SDL_Texture> texture(raw_texture_pointer, [](SDL_Texture* p){SDL_DestroyTexture(p);})But personally I would rather use a map of textures instead and delete them all at the end. I'm doubtful you would run out of memory on your graphics card.

In general I would recommend using C++11 features, or at least not to be intimidated by them. There's some useful stuff in there.


But onto the main part.

Quote
See, I really like the idea of NOT mingling any SDL code with my Thing code. What if I decide to swap out to a totally different graphics system later? But a lot of tutorials seem to do things like store pointers to a critter's texture within the critter's class itself, or give the class a "texture" object holding the texture-pointer that knows how to draw itself. That feels iffy to me... In an ideal world, I think I'd prefer my Things to continue to operate in a way that wouldn't be harmed by ripping the entire graphics system out. Is that stupid?

You might be overthinking your need to swap out graphics systems. But if you still would like to keep the possibility... If you don't want to hold raw pointers to textures and the like, then you can make a wrapper for the graphical stuff, and just call MyTexture.draw() or something of that sort, and then you can later swap out the contents of MyTexture and all should be fine and dandy.

Quote
I understand that a way some people do it is to have the "Thing" not know anything more than an identifier for its sprite, and have a "TextureRenderer" object that can take that information and use it plus the SDL renderer/functions to draw things. But there's a lot of big gaps in my understanding of how exactly that works... what gets sent where and how, mostly. Does the Thing still ask to be drawn itself, somehow? (Like Thing1.drawsprite()?) Do you ask the TextureRenderer to draw it? (TextureRenderer.draw(Thing1.sprite)?) Some kind of intermediate function or object? (DrawThinger(Thing1.sprite, TextureRenderer)?) What data is being passed where in each case? I've been googling about it for days and still don't fully understand how to apply it...

You can do it whatever way seems natural to you. You can do it either way, as Renderer.draw(thing), or as thing.draw(renderer), or as thing.draw() with some global renderer somewhere. Use whatever seems the most readable to you.

I personally prefer thing.draw(renderer), to keep the rendering logic in the class itself, but render.draw(thing) also makes sense. I've seen some things do it so renderer.draw(thing) calls out thing.draw(renderer) which then does the drawing.

Code: [Select]
class thing {
Texture texture;
int x, y, w, h;

void draw(Renderer r) {
r.render(texture, x, y, w, h);
}
}
VS
Code: [Select]
class Renderer {
SomeLibraryRenderer r;

Texture thingTexture;
void draw(Thing thing) {
r.render(thingTexture;, thing.x, thing.y, thing.w, thing.h);
}

//or if not all things have the same texture
void draw(Thing thing) {
r.render(thing.texture, thing.x, thing.y, thing.w, thing.h);
}

//or if you want to decouple completely
void draw(Thing thing) {
r.render(Textures[thing.type], thing.x, thing.y, thing.w, thing.h);
}
}

Quote
Just to make things more Fun and complicated, there's no single "Thing" sprite I can just plug in... Instead, each Thing has a set of stats representing appearance that are randomly generated when it's created. So drawing a thing actually involves layering several semitransparent textures (chosen from a list of possibilities) together, and there's no way to know which textures a given Thing will need until it's created at runtime, only the list of all possibilities. In fact, each Thing will eventually need multiple "layered sprites" based on their set of stats corresponding to different "views" (front, back, etc.).
I guess ideally the Renderer doesn't have to know any of that and only receives/parses requests to draw a given texture in a given place... Is that unrealistic, though? I still can't quite picture how it would work.

Well, you can make a Map or Vector of textures. Eyebrows[1] to get the second kind of eyebrows or whatever. Or have a spritesheet.
If you need multiple things drawn, then you just call draw multiple times.
Code: [Select]
class thing {
Texture back;
Texture front;
int x, y, w, h;

void draw(Renderer r) {
r.render(back, thing.x, thing.y, thing.w, thing.h);
r.render(front, thing.x, thing.y, thing.w, thing.h);
}
}
Code: [Select]
class thing {
int eyes;
int eyebrows;
int x, y, w, h;

void draw(Renderer r) {
r.render(EyeTextures[eyes], thing.x, thing.y, thing.w, thing.h);
r.render(EyebrowTextures[eyebrows], thing.x, thing.y, thing.w, thing.h);
}
}

TLDR:
Is it possible/desirable to make a system for drawing data-only game entities where the entities are totally ignorant of the drawing system?
Pretty much.

If so, how do you get the necessary information sent between them?
Renderer gets passed a thing or a pointer to a thing or reference to a thing, and takes values from it for drawing.

Does it all fall apart with my layered-sprite requirement, where you need instance-specific data from the entity to know which textures to draw?
No. The layered sprite thing has pretty much no effect on anything at all.
« Last Edit: June 07, 2017, 02:55:13 pm by cerapa »
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

DeKaFu

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10580 on: June 07, 2017, 05:03:16 pm »

Wow, thanks for the thorough response!

I suspect you're right about overthinking the need for modularity. I've already fallen into the trap of "trying to come up with complicated solutions for problems I don't actually have yet" a couple times before on this project, heh.

I'll think over those different options and try to decide what feels right. Right now I think I'm leaning towards the Renderer.draw(Thing) method. There's a couple details I think I still need some clarification on, though...

All your examples have the x,y,w,h in the Thing itself, and to me that doesn't feel like the right place for it, because a Thing doesn't exist at any particular coordinates. It just sits abstractly in a vector. The front, back, etc. sprites would be rendered at the same time at different places on the screen (picture something like character concept art, with multiple views of the same thing) and not all at the same size.

In that case, would the correct place for the coordinates/dimensions be inside a wrapper class around the texture pointer? Or would they be something you'd want to just specify in the function at the time you called it? (for example... Renderer.draw(Thing, x, y, w, h))?

Also, if I'm using the Renderer.draw(Thing) method, in that case, the only information I need to store in the Thing is which textures it wants drawn (e.g. the "int eyebrows" values), correct?


As another aside, I am a tiny bit concerned about texture size in memory, not really having any context for "how much is too much"... For example, if I load everything at program start, it's looking like I'll need to load 30+ 700x600 textures into memory for the front view alone. They're not very big as PNGs, but I understand they uncompress in memory and take up a lot more space?
Is that anywhere near a level I'd need to be concerned about? Sorry if that's a silly question.
Don't really want to worry about optimizing texture-loading until absolutely necessary. :P
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10581 on: June 07, 2017, 05:19:08 pm »

As for modularity, you can indeed make it so modules only know the bare minimum to do their job, and don't know specifics about the implementation of other modules.

e.g. say you have a "critter" class with an "sdl::texture" pointer. Get rid of the pointer, make a "typedef int TextureHandle" instead, which is just an int pointing into some textures data structure elsewhere, but it enforces type safety because of the typedef.

Then in textures.h you define a bunch of functions for doing things that need to know about textures, e.g. whatever you need, load a texture from a file, getting an index back, delete a texture, change the currently bound texture, etc. This .h file doesn't even need to define a single class, just the interface.

Only textures.cpp has the actual sdl::textures related data structures in there, and all other parts of your program make service requests through the interface defined in textures.h

This takes a little to set up, but the end result is worth it, especially if you end up with many cpp files with many includes. If the client cpp files only know the barest minimal information about the interface it's meant to use, there are less dependencies, it's easier to debug errors, and compile times are faster, especially if the data structures need to change.
« Last Edit: June 07, 2017, 06:31:59 pm by Reelya »
Logged

cerapa

  • Bay Watcher
  • It wont bite....unless you are the sun.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10582 on: June 07, 2017, 05:58:13 pm »

All your examples have the x,y,w,h in the Thing itself, and to me that doesn't feel like the right place for it, because a Thing doesn't exist at any particular coordinates. It just sits abstractly in a vector. The front, back, etc. sprites would be rendered at the same time at different places on the screen (picture something like character concept art, with multiple views of the same thing) and not all at the same size.

In that case, would the correct place for the coordinates/dimensions be inside a wrapper class around the texture pointer? Or would they be something you'd want to just specify in the function at the time you called it? (for example... Renderer.draw(Thing, x, y, w, h))?

Yeah, you're correct. I was thinking of things defined by their on-screen coordinates when I wrote those.

At call time would be best. The wrapper should hold the texture and texture coordinates(so you can do spritesheets and texture atlases), and at call time you specify the location to draw. In this case you would need to specify 3 loca(tions. Or do something like "Renderer.drawThing.front, x, y, w, h))" or have an enum and "Renderer.draw(Thing, FRONT, x, y, w, h))" and call that 3 times to get all sides, might be more readable than just a fuckton of parameters.

Also, Reelya has some nice ideas.

Quote
As another aside, I am a tiny bit concerned about texture size in memory, not really having any context for "how much is too much"... For example, if I load everything at program start, it's looking like I'll need to load 30+ 700x600 textures into memory for the front view alone. They're not very big as PNGs, but I understand they uncompress in memory and take up a lot more space?
Is that anywhere near a level I'd need to be concerned about? Sorry if that's a silly question.
Don't really want to worry about optimizing texture-loading until absolutely necessary.

Each would take around 4*700*600*2= 3,2 megabytes(assuming mipmaps, half that without them) and graphics cards these days have a couple of gigs of dedicated video memory. You would need at least 300 to hit a gigabyte.
Logged

Tick, tick, tick the time goes by,
tick, tick, tick the clock blows up.

3man75

  • Bay Watcher
  • I will fire this rocket
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10583 on: June 08, 2017, 02:58:28 pm »

I made thing work in Java. I went for a training exercise where the program prints out an object with things inside which in my case is a space marine chapter. I can make 1000 space marines with the name of recruit, the awesome weapon known as a bolter, and have health of '10'.
Spoiler (click to show/hide)
Spoiler (click to show/hide)

Inside are my two classes. Kinda proud I was able to do this on my own :)
Logged

Reelya

  • Bay Watcher
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10584 on: June 08, 2017, 03:27:15 pm »

I'd suggest learning from here how to make very small incremental changes, in a way that allows you to build more complex stuff.

Step 1 - make an array called "WeaponTypes" of type string, which holds your weapon names. Change the BlankMarine's Weapon field to be an int, and look up the array when the name is needed.

Step 2 - make WeaponType into a class instead of a string, but put the string inside it (as "Name"), get it working again with this (should be asimple as appending .Name when looking up the names)

Step 3 - add other fields to WeaponType as you wish, such as range, rate of fire each.
« Last Edit: June 08, 2017, 03:38:07 pm by Reelya »
Logged

flabort

  • Bay Watcher
  • Still a demilich, despite the 4e and 5e nerfs
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10585 on: June 08, 2017, 04:00:06 pm »

Sounds like you're going to have to chop it up and construct your date and time manually.  In Google Docs, and it sounds like this is in its Excel-analogue, DATEVALUE and TIMEVALUE won't work on the whole, but I just ran a quick test and they'll work on their appropriate component halves.  Moreover, due to how Excel constructs date and time-formatted serial numbers (to wit, the former as integers and the latter as fractional values), you can then simply add these back together and get a nice convenient datetime-formatted serial number. 

So, for your case where the date string of the format cited is in F4, what you want should be something like...
Code: [Select]
=DATEVALUE(LEFT(F4,FIND(",",F4,FIND(",",F4)+1)-1))+TIMEVALUE(RIGHT(F4,LEN(F4)-FIND(",",F4,FIND(",",F4)+1)-1))This spits out a lovely Excel-formatted standard datetime number, nearly guaranteed to be unreadable to human eyes unless parsed through Excel's (or Google Docs') cell formatting, and just-as-guaranteed to work quite nicely with any other date-time functions such as NOW(), TODAY(), or DATEDIF().  Since it's a big ol' blob of text right there, here's how it breaks down, just because I'm in a bit of odd, verbose mood at 3 AM and not because I think you actually need it this done so granularly.  I mean, you're working with XML and XPath queries, so you almost certainly know all of this part already; this is more because I'm in schoolteacher mode and can't leave it as just that. :P

Awesome, thanks. I hid collumn G in my example, which is where I put your formula, but it works perfectly. I can now perform math on it like a boss.
Spoiler (click to show/hide)
Now I need to figure out a way to reduce the XML calls so I can speed up loading.

« Last Edit: June 08, 2017, 04:08:02 pm by flabort »
Logged
The Cyan Menace

Went away for a while, came back, went away for a while, and back for now.

inteuniso

  • Bay Watcher
  • Functionalized carbon is the source.
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10586 on: June 19, 2017, 10:17:36 am »

A succinct write up on coding an automated voice/text notification service, with call-in registration. Not included are registration-via-SMS, nor a handy admin interface; it also uses the global variable (egads, non-specificity! The horror!).
Logged
Lol scratch that I'm building a marijuana factory.

milo christiansen

  • Bay Watcher
  • Something generic here
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10587 on: June 20, 2017, 02:36:06 pm »

I would like to extend heartfelt condolences to everyone who needs to write SQL code for a living.

SQL is, in my opinion, the COBOL of the modern world. All that horrible verbosity, the preference for all caps keywords, the retarded syntax...

The worst part is that everyone​ seems to be fine with this. How is
Code: [Select]
CREATE TRIGGER triggerName AFTER INSERT ON tableName FOR EACH ROW BEGIN ... END;
better than, say
Code: [Select]
tableName.triggers.triggerName.AfterInsertRow{ ... }
Or any other of a number of other syntaxes I can think of right off the top of my head?

Oh well, at least I only have to use it for a little bit...
Logged
Rubble 8 - The most powerful modding suite in existence!
After all, coke is for furnaces, not for snorting.
You're not true dwarven royalty unless you own the complete 'Signature Collection' baby-bone bedroom set from NOKEAS

Telgin

  • Bay Watcher
  • Professional Programmer
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10588 on: June 20, 2017, 03:43:12 pm »

SQL is pretty terrible.  I'm really not sure what justifications there are for its syntax, except that maybe someone thought it would be easier to learn and teach, and be more standardized.  I don't think it really succeeded on the standardization part, at least past the basics.

Using a pure textual approach to commands does simplify interfacing with it, in theory at least, since you don't have to write native support in your language or library for every command.  It also opens up the potential for a million and one injection attacks.

I'm kind of curious what the prevailing opinions are in the industry.  I'd like to think that most would agree that it's antiquated and frequently hidden behind ORMs anyway, but it's also ubiquitous and therefore pretty difficult to replace.
Logged
Through pain, I find wisdom.

milo christiansen

  • Bay Watcher
  • Something generic here
    • View Profile
Re: if self.isCoder(): post() #Programming Thread
« Reply #10589 on: June 20, 2017, 04:07:00 pm »

but it's also ubiquitous and therefore pretty difficult to replace.

Unfortunately.

Oh well, I'm mostly done with the SQL part, now I just need to interface the C code for the database library with the Go code for my server.

What am I doing? Writing a audio metadata server, part of the backend for my planned media player. I got tired of not having a cross platform media player with the features I want, so I am writing my own. The result will probably be 2-3 separate applications, several lightweight backend servers running on my NAS or my raspberry pi, and a client that runs on everything else.
Logged
Rubble 8 - The most powerful modding suite in existence!
After all, coke is for furnaces, not for snorting.
You're not true dwarven royalty unless you own the complete 'Signature Collection' baby-bone bedroom set from NOKEAS
Pages: 1 ... 704 705 [706] 707 708 ... 796