2015-01-07 14:11:13

Hi, I'm back! smile
I was wondering if anyone has some suggestions as to the best ways to develop a kind of radar, that detects what's in front of the player for maybe 4 or 5 steps, in a half-circle? I've tried to do this, but in its current form it causes the game to freeze every time it's activated, I'm sure this is because of the for loop and wait statement, but I'm also not sure of any other way to go about it.
Dropbox link:
https://www.dropbox.com/s/i7f5rj63a6egq … r.bgt?dl=1
Any suggestions would be appreciated! smile

Prier practice and preparation prevents piss poor performance!

2015-01-07 15:33:07

This is where the typical architecture breaks down and is also why I advocate reading sighted game programming tutorials.  You'll need to architect your whole game to not use wait statements save in exactly one place.  The typical approach to this is to define objects with a tick method, put them in a list, and call all the tick methods every time through your main loop.  The only thing allowed to call wait, ever, is the last line of your main loop.  This allows the radar to have a function called at a known time.  You then replace the for loop and wait statements for the radar with two counters: the first being the angle at which you're currently pointing and the second being how many ticks to wait before incrementing again.  Something like this (Python):

def tick(delta):
 if wait_counter != 0:
  wait_counter -= 1
  return
 radar_angle+= 1
 if radar_angle >= max_radar_angle:
  radar_angle = min_radar_angle
 sound=compute_radar_sound(player_position, radar_angle)
 sound.play()
 wait_count = 5 #or whatever.\

The delta parameter is the time between ticks.  This is useful because you can replace the integer count of ticks with a floating point count in seconds and then subtract delta instead.  This lets this particular bit of code be completely independent of how fast the game ticks.  I'm obviously leaving out a lot, but this should get it across.  I'd make all the tick methods take the delta and just ignore it if you don't need it: the end result is that you have the information and your new main loop can be like 10 lines.
You can abstract the waiting functionality into a base class, as well as other behaviors.  Using this architecture, you can implement bases that call a function every x seconds, call a list of functions at given times in a loop, etc. Perhaps most useful is a base class that calls a function exactly once after a given wait, but which has a method on it to schedule the next one.  This particular configuration can represent almost anything: a call rescheduling yourself is the above logic, a call rescheduling the next function in a list of events is a timeline, and a call which conditionally schedules the next function is a pretty easy to read finite state machine.

My Blog
Twitter: @ajhicks1992

2015-01-07 18:44:04

Camlorn is right on track. The loop-and-wait thing works if you never have multiple things happening simultaneously (or as close to simultaneously as possible, anyway).

In BGT, you _could_ use timers to keep track of these various independent mechanisms, but can you imagine how messy that could get if you pause the game for any reason? (Sengoku Jidai was programmed rather carelessly, to be honest, because I wanted to make something and my more careful projects were stalling. And, lo and behold, I keep finding an instance where I failed to pause a timer for one of the numerous game-stopping menus, and people wind up starving for it. And Sengoku Jidai doesn't have anywhere near as many timers as it could, because I still tried to do it more frame-and-counter-style, menus aside.)

看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.

2015-01-07 20:19:56

You can use timers in any language.  There is only one good reason to even consider it: a fully online game that never pauses.  But probably not even then.  Being able to  work with time in strange ways is an amazingly helpful thing.
That said, you can replace the wait with a timer that calls the global tick method which in turn calls tick on everything else; this may be advantageous.  You still have a main loop, it just doens't look like one.  I'm not sure what facilities the BGT timer provides, but when I write my own (I do on occasion) I make them such that they'll "catch up" if a tick takes too long because of CPU or similar.

My Blog
Twitter: @ajhicks1992

2015-01-07 21:54:46

+1 for post 2.
An important architectural concept for game programming, and explained very well.

~ Ian Reed
Visit BlindGamers.com to rate blind accessible games and see how others have rated them.
Try my free JGT addon, the easy way to play Japanese games in English.
Or try the free games I've created.

2015-01-08 04:40:56

Ah, okay. So just make a timer then, and call the update method every time it's elapsed?  Or I could put the timercheck in the update function itself. I do that with a couple of my classes, doing that for this didn't even cross my mind, hough. Thanks very much! smile

Prier practice and preparation prevents piss poor performance!

2015-01-08 16:55:19

You don't need timers.  You do exactly what I did in post 2.  And then:

while playing:
 for i in all_tickers:
  i.tick(frame_rate)
 wait(however long)

Determining the time to wait can take just a little math if you want it to "catch up", but this is your entire main loop and you certainly don't need to do so.  You do not put anything else here.  Anything else belongs in one of the all_ticker objects.
If BGT timers allow you to tick them instead of using your system clock, you can do that.  But I'd suggest just using the counter and/or writing your own base class that uses the counter and having your tickers inherit from it.  The former certainly isn't hard, and the latter is like 20 lines tops.  What I am saying about timers is that you can turn that loop into a function that reschedules itself instead of waiting if you want, not that you should use them for everything.
You can stick keyboard here. You can stick enemy AI here.  You can and should stick everything in what I'm calling a ticker--it's the simplest non-blocking architecture and it's how even the big sighted games do this kind of thing.
And on that note, I'm now wondering how close BGT would be to being able to implement something like Twisted in it.

My Blog
Twitter: @ajhicks1992

2015-01-08 20:05:15 (edited by matt1211 2015-01-08 20:06:38)

Hi, thanks for the suggestions. I don't completely understand, but I'll definitely take a look at some game programming tutorials for information. I'm now trying to figure out though, how I can update the angles the radar is scanning based on actions the player performs? For example, turning or walking. I've now got scanning working, but it doesn't update properly based on the angle of the player. If they walk forwards it still works fine, but I'm not sure how I can make the radar continue through it's sweep as the player turns, without just restarting it from the left.
Thanks again for all the help. I'm the kind of person who mostly learns by trying stuff and seeing what works and such, which is why some of these questios of mine are still pretty basic compared to others.
smile

Prier practice and preparation prevents piss poor performance!

2015-01-08 20:59:13

You're going to have to record the angle on the radar as an offset, say that it always goes from -45 to 45 for example.  You then compute the actual angle by adding this offset.  Because of the pattern I am describing--that you have tickers as a class--you can just store the offset on the class and re-read the player's facing direction and position every tick.  You don't want to build the whole sweep ahead of time, you want to build it as you go across.

My Blog
Twitter: @ajhicks1992

2015-01-10 03:31:43

Hi, I'm still struggling with the concept of frames and ticks. I understand how it can be helpful, and I understand your code in post 2, I'm just not sure how for example, you'd tell the game how to tick everything properly, given a certain amount of time per tick. I've looked at some game programming tutorials, but have been having a bit of trouble finding a good one. Do you have and recommendations?
Thanks very much!

Prier practice and preparation prevents piss poor performance!

2015-01-10 04:05:57

I'm afraid not.  I've gone through like 2 computers since I last looked at it.  i'm now at the point where I can tell you all about DSP, and you probably do not want to see the articles I read at this point (I've been having huge mileage with an entity component system, but that's not going to help you now in any way).
What is the difficulty?
If it's just getting things to tick, see my code in post 7.  You'll need to use polymorphism.  Make a ticker base class with a single method called tick, have everything inherit from that, and then create all the different subsystems of your game somewhere and put them in a list that your main loop knows about.  Not much more to it than that.  You move the chunk of code that checks for input into one of the ticker subclasses, and tell it about all the other things it might want to touch--i.e. turning the radar off and on means you're passing it a radar instance.
It can be made much cleaner than this implies, but I'm trying not to go too far ahead.

My Blog
Twitter: @ajhicks1992

2015-01-10 05:56:02 (edited by CAE_Jones 2015-01-10 06:00:52)

For BGT, I wrote a clock class that takes care of the timer shenanigans. All you need to specify is how much time should pass between the start of each frame.
A main function might look like this:

void main() {
clock fps(50); // The constructor takes frames/second as a parameter and determines the delay for you.
double frametime=fps.delay; // This is the target time that passes between frames.

show_game_window("Game with frames");
while(true) {
keycheck();
step_game(frametime);
update_other_things(frametime);

fps.tick();
}
}

In practice, I'd include a method (I usually call it step) that takes the amount of time that passes as a parameter, for each class that needs time-sensitive updating. Enemies and radars both fall into this category. You could use an interface for tickable objects, but I don't see the need for it most of the time.

If the step/tick/update method is the part that's throwing you off, odds are that most classes like this will include this sort of thing:

class TimedObject {
double counter=0.0;

/* [...] */

void step(double dt) {
counter-=dt;
if(counter<=0.0) {
// Time's up: do whatever needs doing. Update your radar angle, for example.

// Reset the counter. As an example:
this.counter=1000.0; // Assuming milliseconds.
}
}
}
看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.

2015-01-10 06:25:08

Hi, I think what confuses me is how ticking is different from something like, while (true) {
keyboard_function();
wait(5);
}
and how to know when to call something like tick, and how calling tick methods will effect the game. I'm really sorry I'm having so much trouble grasping this concept. It's something that I've never heard about before, but I see how it could be very useful so I really want to understand it.

Prier practice and preparation prevents piss poor performance!

2015-01-10 07:02:06

This might be a little much for one post.  I apologize in advance if it is.
To keep using my invented word...
Keyboard_function is a ticker.  Whatever keyboard_function normally does goes inside one.  In reality, you usually end up breaking keyboard handling up too, but that's neither here nor there for the time being (but we'll get there if this conversation goes on much longer).
Your radar is a ticker.
your physics system is a ticker: add velocity to all objects with one, tell the objects they've collided by calling a.collides_with(b) and b.collides_with(a), etc.
Enemy AI is a ticker.  When it ticks, it figures out what the enemy should be doing, typically (for the stuff being discussed here) setting the velocity on the enemy.  Enemy AI is the first example of a ticker which may not always finish the tick, as pathfinding can be expensive.  I normally put enemy AI in the enemy class and register it as a ticker--this allows different enemies to have different AI.
Here comes the key insight: none of these are "special".  Each of these is a game object just like all others.  What you do is register them in a list; we've covered that before.  But if you make sure that all the objects in your game can access that list, you can suddenly have one-of-a-kind enemies and stuff.  The main loop doesn't care what needs ticking, it just cares that it's got the tick method on the objects therein.  So everything can inherit from the base class if you want, and everything can have its own little slice of time whether or not it's used.  It's like being able to run bunches of really simple games instead of one big one: everything has its own main loop, it's just that they all start with a function declaration instead of a while statement.  Since you're not using threads (which make learning this particular pattern look like cake), you can be assured that only one ticker is touching the world at a time--no need for typically complex concurrency stuff that gives basically all programmers headaches.
Instead of waiting, you use what is called a finite state machine.  The idea is that you might be in one of various states right now, so you set a flag and use if statements.  This is the equivalent to blocking without actually blocking.  Your radar is the simplest example.  It can be either on (in which case it is doing something) or off (in which case it is not).  You've almost certainly built finite state machines already; whether or not you know the words, it's a super common game design pattern.  To apply limiters and lag, you replace them with more counters, i.e. the gun cant' fire again for .3 seconds.
Global variables are bad.  The particular pattern I like to use to deal with the fact that tickers need to know about each other and other stuff outside themselves is called dependency injection (I mention this so you can have a googlable term).  If your radar needs to know about whatever object is responsible for holding the level map, it either gets a reference to it passed in via the constructor or looks it up on your game object--also passed in via the constructor.  I personally prefer the latter.  When I set something up like this, I usually put the main loop of the game inside of a game class and then hang things like the current level off of it.  Tickers can then access important game state through that avenue.
To make two tickers representing important things know about each other, I suggest either the use of instance variables on your game object or the use of a dictionary (BGT might call this something else) mapping names of important things to tickers.  The latter is probably a bit advanced for what you're doing, but you'll probably end up using something like it down the road (mapping things to unique ids like that is great for saving to disk and doing network stuff).  But in truth, I find that tickers don't often talk to each other.  They can, and there's nothing wrong with it-just, if you do this right, each ticker is completely responsible for exactly one concern, and there isn't that much mixing.
To make tickers know about important things like the level map being changed, I typically add more empty methods to the base class that act as events: level_changed, for example.  And then you just call them all without caring if anything happens (which can be faster than most naive lookup schemes and avoids a lot of bugs--do not worry about performance).
You might try looking into XNA tutorials.  I don't have specific ones as it's been like 6 years at this point.  XNA is big on this particular pattern, aimed at new game programmers, and was pretty popular for a few years.  It's also the earliest thing I can recall seeing this pattern in, and you can find some other useful stuff floating around that talks about saner ways to handle input (even if they don't seem so at first).
And finally, some motivation for you, as i know the proceeding is possibly like hitting your brain with a brick.  If you want a game which is both complex in terms of game mechanics (though not necessarily in terms of coding, believe it or not) and also bug-free, you need this pattern.  More complicated variations on this pattern power almost every online service you interact with on a daily basis.  If you ever have or want to work with microcontrollers or robotics, you see things that are similar to what we're talking about here.  I'd be willing to bet quite a lot that Swamp looks something like this internally.  If you take this to the next level, you could be hired as a node.js or twisted programmer (both of which are frameworks that use a much more advanced version of this pattern and power huge chunks of the web).  Every windows app eventually boils down to a message loop, which is this in essence, at least in most GUI framework internals.  The list goes on, I'm sure.
You don't have to roll this out all at once.  Start by doing it for your radar, and then see where it goes.  Rearranging your entire idea of how games and other software is structured does not happen overnight.

My Blog
Twitter: @ajhicks1992

2015-01-10 17:34:26

The difference between

while(true) {
functions(5);
wait(5);
}

and

while(true) {
functions(fps.delay);
fps.tick();
}

Is minor when you're doing something simple. You can go ahead and do it the first way, if you want. The only real advantage to the second way is that it attempts to keep frame duration consistent.

But in the end, your game objects will need to know how much time has passed since they last did anything. It can be done with timers, but the more it looks like what Camlorn described, the easier it will be in the long run.

看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.

2015-01-12 15:03:57

Hi, so, I think I'm, incredibly close to figuring this out. I do have one question, though. What's the best way to regulate the time that passes between ticks? I know that's the entire point of the thing, and I looked at that frame clock for bgt, but I'm not sure how much it helped me. On the bright side, I can practically feel my brain repeatedly shattering and rebuilding itself, better than before! So that's always a pluss.
Thanks for all the great suggestions!

Prier practice and preparation prevents piss poor performance!

2015-01-12 16:04:28

You can use a constant value, and this is likely to be fine.
Or (Python again, sorry):

while True:
 start =time.time()
 do_stuff()
 end = time.time()
 took = end-start
 if took >= wanted_time:
  continue #we don't wait because we took too long.
 time.sleep(wanted_time-took) #wait for the remaining part of this tick.

To figure out wanted_time, do 1 over the desired frame rate.  I suggest just passing the frame rate to all your functions, at least for now.  Some advanced games will compute the actual frame rate in realtime and make up for slowing down by actually modifying the physics formulas, but you are very unlikely to need this functionality.  At least in my opinion.  If you do, we can talk.

My Blog
Twitter: @ajhicks1992

2015-01-12 18:31:09

Thanks! I think I am beginning to understand this.

Prier practice and preparation prevents piss poor performance!

2015-01-12 18:39:32

Good. We really, really need more people around here advocating for it.  It is frustrating to keep watching people use blocking architectures and throwing all their stuff right in the main loop.  Sighted people solved these problems for us like 20 years ago, and yet here we are with what few tutorials exist advocating not using any of these techniques.  I kind of understand why, but still-everyone who is actually serious about it hits this point, and that's a ton of code that has to be ported or thrown out.

My Blog
Twitter: @ajhicks1992

2015-01-14 03:40:17

The wait function in BGT was pretty novel for me, on the grounds that I'd been working primarily in Java and Javascript up to that point.
Javascript first. This was way before HTML5. Timers with callbacks were the only way to go.
Java's Thread.sleep() is just not worth it. AWT and Swing were the only real options when I started, and they are designed to be event-based rather than loop-based. Throwing a Thread.sleep in there is always painful, even if there's an actual use for it.

Someone *could* write a similar event-based architecture for BGT, assuming anyone would use it.

看過來!
"If you want utopia but reality gives you Lovecraft, you don't give up, you carve your utopia out of the corpses of dead gods."
MaxAngor wrote:
    George... Don't do that.