Jump to content

  • Log In with Google      Sign In   
  • Create Account

rip-off

Member Since 16 Mar 2005
Offline Last Active Today, 08:34 AM

#5266552 Having a problem to get values from different methods which contain different...

Posted by on 15 December 2015 - 03:13 PM

Yes, you definitely don't want to use floating point equality. I was going to mention about bounding box collisions but it slipped my mind, but Googling for "XNA sprite collision" or "XNA bounding box collision" should return some useful results.




#5266416 Having a problem to get values from different methods which contain different...

Posted by on 15 December 2015 - 03:17 AM

It is possible that the error messages you were getting were because you were calling the "isHit" method incorrectly. In your current code, you'd have to call it like this:

if (someEnemyObject.isHit(someBulletObject, someEnemyObject, someBoolean))
{
   // There was a hit!
}

 

Note that the boolean parameter doesn't do anything (it is assigned to and returned), so we can remove it from the "isHit" method:

public bool isHit(Bullet b, Enemy e)
{
    if (b.position.X == e.ePosition.X && b.position.Y == e.ePosition.Y)
    {
        return true;
    }
    else
    {
        return false;
    }
    
}

 

Now to call it:

if (someEnemyObject.isHit(someBulletObject, someEnemyObject))
{
   // Hit!
}

It is now a bit odd to have to pass the enemy object to the method in two ways, the explicit parameter but also using the "this" mechanism (by calling the method on a given object).

 

There are a couple of solutions to this, but given that this logic crosses two different objects, we can just move this logic into the game class where the two different objects are interacting anyway:

private bool isHit(Bullet b, Enemy e)
{
    if (b.position.X == e.ePosition.X && b.position.Y == e.ePosition.Y)
    {
        return true;
    }
    else
    {
        return false;
    }
    
}
 
 
protected override void Update(GameTime gameTime)
{
    if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
        Exit();
 
    if (Keyboard.GetState().IsKeyDown(Keys.Space) && pastKey.IsKeyUp(Keys.Space))
    {
        Shoot();
    }
 
    pastKey = Keyboard.GetState();
 
    // Level Check ----- Level Check ----- Level Check ----- Level Check ----- Level Check -----
 
    Enemyss();
 
    // Updates
    UpdateBullet();
    pla.Update();
    foreach (Bullet bullet in bullets)
    {
        foreach (Enemy enemy in enemies)
        {
            if (isHit(bullet, enemy))
            {
                // There was a hit!
                // Maybe do something like enemy.TakeDamage();
            }
        }
    }
    base.Update(gameTime);
}

If your game class starts getting very long, you can move all the bullet and enemy game logic handling into a separate class, e.g. "World" or something.

 

A god design rule of thumb is to try not to let too many classes know about the overall program state. So try keep the bullet and enemy class to simple objects that don't really know or care about the existence of other game objects, and just rely on higher level parts of the program to inform them about interesting events from the outside world (like having an enemy.TakeDamage() method for example).




#5265129 Threaded pathfinding on dynamic tilemap

Posted by on 06 December 2015 - 08:16 AM


The problem is I cannot queue up much tasks. Say a building requires 2 stones. If I would start queuing up these 2 tasks there is a risk the second task is pointing to the same stone.

Then you can make the tasks a bit higher level, such as "find the nearest N stones to location X, Y", or as samoth suggested create a task dependency system, where the second search is not attempted (or queued) until the first one has been actioned (e.g. the stone has been reserved).

 


Anyway, I already know I need the threading since I have potentially large maps 6.000.000 tiles and have a lot of experience with pathfinding on these tile maps. I could implement hierarchical pathfinding and that would help a ton on performance but I think it has it's charm when units do not react instantly anyway. I have also done tests on DataStructures and looking up or sorting 1.000.000 items just cannot be done in a couple of ms and these are the numbers I'm aiming for. Just a single battle with 20 units can leave hundreds of items behind. Even if I would cut up everything in chunks there still might be some items of interest all across the map and that would kill performance on the main thread. So to keep the UI responsive threading is afaik the only way.

Remember that multi-threading can only yield a maximum of linear performance gain over single threading, based on the number of execution units on the end-user's machine. Algorithmic changes can have dramatically better gains.

 


... but I think it has it's charm when units do not react instantly anyway.

You can always add a tunable delay between when the information is known and when it is acted upon to get the same behaviour.




#5265070 Threaded pathfinding on dynamic tilemap

Posted by on 05 December 2015 - 04:57 PM


Now as I understand dynamic and threading are conflicting with each other. I cannot issue all these order simultaneously since unit A might go for the same item as Unit B and things will obviously break. How can I deal with this in a proper way? 
As usual, there is no one true way.
 
The first thing I'll recommend is that, where possible, do not share mutable state between threads using manual locking. This is one of the most complex ways to implement multi-threading, and maintaining the correctness of such an approach is going to be a major challenge. It is actually possible to write multi-threaded code that performs slower than similar single threaded code if this is done wrong, along with risking deadlocking, etc.
 
Instead, prefer:
  • Immutable data structures. Once created, the data can be safely shared between threads/ For example, your basic map layout might fit into this category.
  • Creating copies of mutable state. For example, where the items, buildings and units are at a given time step.
  • Communicating via established thread-safe data structures.
 
 
Let's imagine you already have a single-threaded version of the code that is working correctly. Here is one way you could evolve that into something that can be pushed into a background thread. I'm not saying this is the best way or that you would have to actually follow these steps prescriptively, but it hopefully will illustrate a way around the issue you identified. In particular, I've not done path finding so there might be more specific techniques that are better suited to that problem.
 
The first thing is to change your existing code so that it can execute out of order. So, for the example you cited, when the user orders a stockpile, create an object that represents this command and place it in a queue (e.g. "find the nearest sword at map location X, Y"). Then, between time steps, pop one or more tasks from this queue, execute the path finding logic and store an object that describes the results of the path finding computation in another queue (e.g. "the nearest sword to X, Y was at XX, YY"). Inside the game logic, pop any completed results and attempt to take the action (you'll need some way of linking the commands with the results). If you find that the results have been invalidated (e.g. that sword object has moved or otherwise unavailable), you can just throw that computation away and re-issue the command. It will depend on the game, but for most such games, the user won't be issuing so many orders that there will be a lot of wasted work.
 
At this point, consider stopping and evaluate the resulting gameplay experience. It might be that with the right tuning on how many commands are popped from the queues per timestep, you have achieved a responsive user interface by essentially limiting the amount of CPU time that pathfinding can consume each timestep. If so, mission accomplished - you don't need to add multi-threading!
 
Should you want or need to continue, the next step is to ensure that these tasks could execute safely on a background thread. Let's assume the basic map layout is be immutable and safely shareable. For state that is mutable, consider having a separate copy for the background task. For example, maybe every time step, the foreground game logic thread will push "building created", "item reserved" and "unit moved" events into a queue. Between computations, the background thread can drain this queue and apply the events to a local copy of the game state.
 
It should be possible to test an implementation of this design without introducing multiple threads yet.
 
Finally, you can push the work into the background. You'll need to ensure that you use thread-safe queuing data structures. Java has standard classes for this, such as the Queue classes in the "java.util.concurrent" package. You'll also need to ensure that your command, result and event objects are thread-safe (e.g. not holding a reference to state that could be accessed by other threads).
 
You'll want to avoid creating threads on demand. Threads are expensive to create, so unless the task is very rare and very expensive, it isn't worth creating a new threads for a single task. You could create a single background thread at startup that is hooked up to these queues. Ideally, it would block when the queue is empty.
 
This kind of design can allow you to have multiple concurrent pathfinding computations, you could create several background threads, each with a local copy of the relevant gamestate - you'd just need to adjust how update events are propagated. This way you can use a "thread pool", where a number of threads are created at startup and are "blocked" on a thread-safe work delivery queue. The number of threads can be configured to be appropriate to the user's machine. Again, the Java standard library has classes for this,  the "ThreadPoolExecutor". This might be especially valuable if you have other interesting, expensive tasks that can be made asynchronous and pushed into the background.
 
If you have other expensive computations that can be made asynchronous, they could potentially share the same thread pool. You can use Futures if you prefer the API they provide. In the example above, I talk about an explicit command and result objects, but that is mostly to illustrate that you have to be careful how you pass data between threads, if you have a Sword class with a mutable Position, then passing that to the background thread is not safe.



#5264954 Concept of abstraction in programming

Posted by on 04 December 2015 - 06:23 PM


The topic focuses on much more on than just a modifier like abstract from java that can be applied to methods or its brother virtual in C++.

Indeed, too much focus is paid to such things. It is not unusual for an "abstract class" or "pure virtual class" to offer little actual abstraction.

 


PROLOG is one of the most abstract languages I've ever used. It's quite old, but basically what you write is very loosely coupled with what actually runs. It is way more abstract than any notion of classes and pointers... Even the order of the commands (the instruction register?) is decoupled from how you write your code. Although it is not heavily used in the industry, it is very well studied in Academia. If you want to experience highly abstract code, try some  Prolog.

This sounds more like the distinction between declarative and imperative programming, and / or the difference between high and low level languages. You can still write very "concrete" (non-abstract) Prolog programs, even if the execution engine has a lot of flexibility in how it might evaluate said program.




#5263780 loop: for(....) {... continue loop; ....} doesn't work

Posted by on 27 November 2015 - 02:54 AM

Note that using == on Strings may appear to work sometimes, this is very likely due to how Java handles String *literals*, which are often de-duplicated to reduce memory usage. Strings loaded from an external source do not get this behaviour.




#5263478 execute constructor of derived class

Posted by on 24 November 2015 - 04:34 PM

The typical rule of thumb is that a C++ class with any virtual member functions should also have a virtual destructor. Note that this also means specifying an empty virtual destructor even where you don't actually need custom destruction logic. This is based on the reasoning that writing code like frob demonstrated is typically only useful if the class in question has virtual member functions worth calling.




#5263149 Random errors in Release builds

Posted by on 22 November 2015 - 10:49 AM

As mentioned, please don't mark threads as "Solved" here, thanks.




#5260385 Singletons and Game Dev

Posted by on 03 November 2015 - 03:53 PM


How would my code look if I had to pass all that state around through function arguments and the like? Wouldn't that make it needlessly verbose?

This is a common argument for global state. The answer can be: "cleaner". Being forced to pass around state incentives programming styles that minimise dependencies and designs that are less coupled.

 

In short, you have constructed a false dichotomy between how your code currently looks and how it would look if you explicitly passed around the state, you are not considering the case where the code looks quite different from how it currently does.

 

 

 

When I was an intermediate programmer I was so proud of my little games with these "sub-systems" that were exposed via singletons. I thought I had a design. Looking back, these were horribly coupled. There were all sorts of dependencies between these so-called "sub-systems" because I didn't learn how to design code that wasn't coupled. If I needed to play a sound, or display something, I could and would reach from anywhere in the code into the relevent singleton and tell it what to do. From experience, I can clearly see that there was no overarching design.

 

That said, I'm not afraid of globals. I probably would still use them, for example as a placeholder while I experiment with an approach, before I know how I want or need the overall design to change. Particularly for smaller programs, a global for something simple and known like a logger or a resource cache is far from the end of the world.

 

I'd never bother with a singleton again. The "once and only once" rule doesn't seem relevant, I've never had an issue creating unexpected instances of something to justify the additional code that a full singleton requires - and the trade off against difficulty writing unit tests would be too big a burden to bear anyway.




#5260033 Collision Detection AS3

Posted by on 01 November 2015 - 03:27 PM

Unfortunately, as Lactose indicates, we don't allow people to get direct answers for their homework here. General questions about collision detection are allowed.




#5259135 Trying to get an idea of what a move object stream looks like in UDP?

Posted by on 26 October 2015 - 09:19 AM

Have you browsed the Networking and Multiplayer FAQ? Question 12 seems particularly relevant.

 


Also, to go one step further with the byte example above, am I going the right direction if I create a packet like protocol, so messages are smaller? In other words would I want to do that for efficiency (common sense? or no?)

Efficiency is relative. Even a fast paced user won't generate too many input commands per unit time, so there probably won't be a huge difference in overall performance in how you encode, transmit and decode such messages. As a counter example, if your game could end up having a lot of active entities on the server, then keeping all the clients up to date with all the entities may warrant much more extra care to avoid performance issues.

 

I'd recommend starting simple. Probably the best advice is to consider versioning your protocol or packets from the start. Including some kind of version identifier offers you the chance to change how your message work and ensure that new clients or new servers can either reject or interoperate with older versions.

 


So there might be an action packet like _ac:m:udlrlrudl and that would mean -> action move up down left right left ... etc. and I implement the parser to handle it locally?

You could do that. Remember if you are writing an action game you'll probably want to transmit the input command as soon as possible, so you are unlikely to be in a position to buffer so many commands at once. If your game is less action oriented, then there will be less consequence to the efficiency of the message.

 

It may be important to sent some kind of time identifier with input messages, so the server can attempt to replay the events from multiple clients and resolve unexpected sequences (if player A and B both attempt to move into the same tile at some point). Remember there is no guarantee the clocks on the server and client will match, so some kind of relative timing identifier must be used.

 


lol - which comes to my next question. After this I can start trying to implement it. How can I keep the server in sync with all clients when moving a monster.

I'd refer you back to the Forum FAQ, which has articles from real games as to how they've handled this. Unfortunately, all those games sounds significantly more complex than the one you're talking about so far, so perhaps there is an element of overkill in some of these approaches.

 

Ultimately, the big lesson of network game programming is that guaranteeing synchronisation (e.g. lock step) is a very expensive way to solve network games, any latency or connection issues will immediately impact on all users' experience of the game. Thus, most games choose to lose this guarantee and try to do their best to hide latency in various ways. Some games can use design and animation to hide most latency (e.g. Age of Empires, where a "Yes, Sir" sound would complete before the unit would respond to the command). Others accept that the clients and the users will sometimes disagree with the server's interpretation of events, and attempt to reduce the impact of such disagreements (such as the Source Engine "rewinding" the server when a player input packet arrives to resolve the event).

 

Ultimately, the network is a leaky abstraction, you cannot make it go away, you can just try to choose a trade off that impacts your game's style least.




#5258821 please help me teach yourself game programming in 21 days

Posted by on 24 October 2015 - 08:03 AM

As the others have mentioned already, what you are asking for is not allowed under copyright law.

 

Topic locked.




#5258409 Problem with save mechanisms

Posted by on 21 October 2015 - 02:03 PM

The stream read operation uses whitespace as a delimiter. You'll need to write something like a newline character between fields to read them back one by one. This will also allow you to use std::getline() for strings, thus allowing you to save strings with embedded space characters.




#5256673 Optimization in Javascript

Posted by on 11 October 2015 - 07:31 AM


I know that the next big thing would be to look again at my code logic and try to find new design ideas to speed things up but since I'm out of idea there...

That is the first thing you should be looking at - this is where the biggest gains are typically found. Micro-optimisation rarely results in orders of magnitude of a difference.




#5254157 Exiting running threads in a DLL when calling executable exits

Posted by on 26 September 2015 - 12:06 PM

Note that the behaviour you described does exist, it is just non standard. So in a way you are correct, once you qualify that it is compiler dependent. Now that the standard has thread support, there is little reason to rely on the older behaviour.

For example, Microsoft's C++ compiler documentation:

ISO Compliant
If you are familiar with the C# volatile keyword, or familiar with the behavior of volatile in earlier versions of Visual C++, be aware that the C++11 ISO Standard volatile keyword is different and is supported in Visual Studio when the /volatile:iso compiler option is specified. (For ARM, it's specified by default). The volatile keyword in C++11 ISO Standard code is to be used only for hardware access; do not use it for inter-thread communication. For inter-thread communication, use mechanisms such as std::atomic<T> from the C++ Standard Template Library.
End of ISO Compliant

Microsoft Specific
When the /volatile:ms compiler option is used—by default when architectures other than ARM are targeted—the compiler generates extra code to maintain ordering among references to volatile objects in addition to maintaining ordering to references to other global objects. In particular:

  • A write to a volatile object (also known as volatile write) has Release semantics; that is, a reference to a global or static object that occurs before a write to a volatile object in the instruction sequence will occur before that volatile write in the compiled binary.
  • A read of a volatile object (also known as volatile read) has Acquire semantics; that is, a reference to a global or static object that occurs after a read of volatile memory in the instruction sequence will occur after that volatile read in the compiled binary.
    This enables volatile objects to be used for memory locks and releases in multithreaded applications.





PARTNERS