Jump to content

Rick

Members
  • Posts

    7,936
  • Joined

  • Last visited

Everything posted by Rick

  1. I've done multiplayer in LE via Lua but I used RakNet instead of enet. Papa, you may want to rethink making it multiplayer (although I know that's what it's all around) because getting multiplayer working is no small feat especially if you have little any experience in it.
  2. self.Material is the same as Script.Material at the top of the script which is a parameter to the script. You fill that in from the editor with whatever material you want that's in your project folder. So you attach this script to anything (a plane I would guess would be best) and assign that Material parameter which will show up in the editor when you attach the script.
  3. If you were using Lua then you'd basically do the same thing as Unity. However it sounds like you are using C++ (which also allows Lua so you could do the same thing but if you want to use pure C++). Go get a copy of RakNet and use that for the multiplayer aspect. Leawerks requires a gfx card right now so you won't use LE at all for the server application (assuming client/server vs peer/peer). Use a state machine for your major states (Logo, Main Menu, Gameplay). App.cpp creates a window, context, world, camera and I like that it does because you will probably use all of those through all the states so no need to create them in each game state. I just pass them through to the states so that I can use them. I place my RakNet network look inside the state manager, and have each state able to register a network message to a state (class) function and the generic loop will see if a message has a function registered to it and if it does it calls it. Now I don't have to mess around with that loop ever again. I simply link class method to network message ID and I get functions called when network messages come in. I do my network messages with a Request/Response idea. The client always makes Request messages to the server that always sends Response messages. Not sure if this is what you were looking for.
  4. Are you sure it's the context giving the issue and not the image you pass to it not being created/loaded? You'd probably get the same error on the same line if that was the case.
  5. Boy, have we wasted so much time and money on teachers then...
  6. OK. There is no need to have the player be global for this to work. So in your collision event you can check if the entity that the engine passed into the event (the entity that collided with the trigger) is the player. You can do this by checking a key value. Let's say you named your player entity "Player". This gives it a "name" key of "Player". So in your collision event you check if entity:GetKeyValue("name") == "Player". Now if that statement is true, the player has just collided with that trigger and the entity that was passed into the collision event IS the player entity. So now you have the player entity available to you without it having to be global or looping over anything. Now you can do anything you want with the player entity. In my teleport tutorial I have a teleport script and in that script it has a variable that says where should I teleport to. In the editor I link the 2 teleporters together so that they know about each on during run-time so that I can transfer the player between them on collision enter, which I can do because I have the player entity from my if check. You would need to do that same setup on linking 2 teleport triggers. Now in your case you wanted relative positions to the teleport pad so that you could position the player, which you have inside the collision function and that's where you would want to do the positioning of the player, on the other teleport pad. You should have all the information you need right inside that teleport pad. You have that teleport information, you have the player entity, and you have the linked teleport information. If you make both your triggers the same size, then inside the collision you can get the offset between the trigger and the player positions, and then inside the trigger, where you already have the player entity because that's what collided with the trigger and the engine passed it into that function for you, you can position the player to the other triggers position, then offset by the same amount. Does that make sense? You have all the information you need inside the collision function so there is no need to loop over anything to get the player.
  7. this makes me sad No. Welcome to scripting Finding specific LE entities between Lua and C++ is easy. Use SetKeyValue()/GetKeyValue() to give some kind of ID and your're good to go. Then just loop over the map's loaded entities and check that key value to see if it matches what you are expecting. I think what some of us thought you were asking is how can you get your own custom C++ class exposed in Lua, which is more work.
  8. Do you have examples of what you are looking to do? Mixing between them via the way Aggror mentions is sort of a pain but once you have the objects setup it's slick to use them. Doing it via shadmar's method he mentions gets basic types from C++ to Lua and is easy to setup but again, it's basic types. I think mixing is a pain. Something to test is what happens when you use SetUserData() in C++ and GetUserData() in Lua. SetUserData() generally let's you pass a class pointer casted as void*, but would be interesting to test what you get back in GetUserData() and how to use it in Lua.
  9. I think libs built in VS need to be built with the version you are using them in. So a lib built in VS 2010 won't work in VS 2013 (I think). http://stackoverflow.com/questions/1600399/are-c-libs-created-with-different-versions-of-visual-studio-compatible-with-ea This is why you see people offer source with build files so that you can build for whatever version you want.
  10. so you guys are using github/bitbucket for everything? All art assets and everything?
  11. Can you show the class? Is that member static? If so you probably didn't init it in the cpp file. If it's a function then you probably didn't create it in the cpp file
  12. What is the best way to share LE C+ projects? Ideally we would want a source control for the VS solution, but something like google drive/dropbox for the LE stuff (maps/models/etc). However since the solution is a subfolder and google driver doesn't seem to let you decide what subfolders/files to NOT sync anytime you change locally it'll update the solution on google drive which isn't what you want because you want that controlled with bit bucket or some other source control. This setup doesn't seem that great, but artists generally don't know source control and you generally don't want binary files in course control anyway. How is anyone else setting this up?
  13. So on my laptop when I opened VS 2013 it gave me the same prompt, but this time when I clicked the Sign In button it prompted me to enter my id/pw and when I did it worked just fine. Not sure why it's not allowing me to do so on my desktop though.
  14. They are all linked together and set to my gmail account.
  15. When I click the sign in button it doesn't prompt me for any id/pw so I can only assume it's using my Win 8.1 account that's link to my Live account and for some reason that's not letting me renew a license. ><
  16. A couple days ago I get a screen popping up in VS Express 2013 Desktop that says my 30 day trial has expired. There is a link that says "Check for an updated license" but when I click it, it just says "Failed to download a new license". There is a Sign In button but it never asks for my username/pw and says it fails. I'm connect online fine. Anyone experience this? I've uninstalled and reinstalled a couple times already. Can't figure this out!
  17. Passing data around is exactly what you should be doing. You should be passing data to constructors like this. That is considered clean, flexible, & testable (again this is real world findings by more than just me). If you find that you are passing 10 variables to a function then that is a hint that something should probably be in a class to help organize things. Take a step back and think about things as real objects. Don't be afraid of classes. A class that has a bunch of unrelated variables (in terms of what a real world object is) raises a red flag. Another hint for easy testing is that you should never use 'new' inside a constructor and instead pass objects to constructors that are already created outside of it for use. This again makes testing much easier. Another tip would be to program to an interface. C++ doesn't have a strict interface but a class that just has just virtual functions and a name that starts with I like (IActor) can act as an interface and help make your design more flexible and easier to test. Although speed is sometimes an issue with games depending on what you are making and this one can sometimes (not likely for a 1 man game) slow down execution. I'm not saying you need to do all this now, but if you incorporate some of these ideas now you may see some of the benefits and you will be moving towards a cleaner, testable, & flexible style of coding. Overdoing it at first if it's new to you will only complicate things. These are often concepts that you need to slow introduce and see their benefits over time.
  18. I guess I'm to dense. Global state is bad (for many reasons) and singletons creates global state, hence they are bad. It's not as if people just made this stuff up. They've ran into the issues and share their experiences to help others avoid it. Moving on. @Mex How do you manage the different states in your game (main menu, gameplay, etc)? In your example, generally you'll load your map close to where you need it and you would want to pass the position (or spawner object) to the player class constructor while you create the player object during map loading. You probably won't like the reasons as to why this is better as I guess you don't do unit tests, but if you were to test things out, what you have makes it harder because you have this global requirement. The question is do you really need that global requirement? The answer is no. So knowing the limited I know about your game, I would say pass it to the Player constructor and store it in there for later use inside the player object. What I see in your example is that your player variable is just an LE entity instead of being it's own class. There are other benefits to wrapping up your game objects into your own classes and using variables to hold the LE types. Think of LE types are just like ints, floats, etc. A player class is a perfect example of this. class Player { private: Entity playerEntity; Vec3 spawnPosition; public: Player(Entity player, Vec3 pos) : playerEntity(player), spawnPosition(pos) { void Respawn() { playerEntity->SetPosition(spawnPosition); } Vec3 GetPosition() { // or if you are lazy just make a function to return the Entity so you can use the already created Entity functions return playerEntity->GetPosition(); } }; Generally your player objects will have things like health, speed, etc and you can nicely contain them all in this class instead of having all those variables floating around where they don't belong. You probably aren't thinking about testing but think about unit testing this vs what you have with global state. This class doesn't have any special requirements of global state so when testing you can do something as easy as: void Player_Respawn() { Entity* e = LoadEntity(); Player player(e, Vec3(0, 0, 0)); player.Respawn(); Assert::AreEqual(Vec3(0), player.GetPosition()); } Note there is nothing messy or surprising about this. You don't have to know that you have to setup some global state before something else can be used correctly. Believe me, I've been on a project before where almost everything was global and it was a nightmare to learn. If you ever stop and come back it'll be hard to remember all the global states that need to be setup before something works. In my example the objects explicitly say what they need to work. If I was to hide a global state inside the Player object much like in your example then it's much harder to figure that out. You may think the small things you have in mind won't matter but they will and they will start adding up and things will be hard to understand how the flow goes pretty quickly. They way you have it setup I would argue isn't clever and isn't needed. Looping over the loaded entities is generally happening at some point where you can create and store the objects inside a class (even if it's the App class) so store them there as normal variables and pass them along to other objects when needed.
  19. I must be missing the idea with that statement in relation to this topic Guppy. What side are you on?
  20. What is this position variable and why do you need it in every class? Can you give some game context on it? The hardest part about globals is not knowing the future. There is no way to make a read only variable that you read in at run-time (ie it's no constant) so nothing stops you, or anyone that may work with your code later in the future, from changing that value. You may not think you want to change it today, but a situation may come up where you need to and now things might get complicated. This is just the general idea as it's hard to say without knowing the game related details of why you think you need this global. Also, when your game is implemented as a state machine you can pass this variable to every state, or make it part of the state class so that it's not global but can still be used in every state.
  21. State machines and the like are not considered spaghetti code. Using globals is what leads to spaghetti code. State machines are very standard in almost all games created. Also being able to unit test code is the standard in all programming and globals make that very hard if not impossible to do. Working inside a function where all state is inside that function and not outside of that function is clean coding that makes things easier to maintain and change later on.
  22. Why Global Variables Should Be Avoided When Unnecessary Non-locality -- Source code is easiest to understand when the scope of its individual elements are limited. Global variables can be read or modified by any part of the program, making it difficult to remember or reason about every possible use. No Access Control or Constraint Checking -- A global variable can be get or set by any part of the program, and any rules regarding its use can be easily broken or forgotten. (In other words, get/set accessors are generally preferable over direct data access, and this is even more so for global data.) By extension, the lack of access control greatly hinders achieving security in situations where you may wish to run untrusted code (such as working with 3rd party plugins). Implicit coupling -- A program with many global variables often has tight couplings between some of those variables, and couplings between variables and functions. Grouping coupled items into cohesive units usually leads to better programs. Concurrency issues -- if globals can be accessed by multiple threads of execution, synchronization is necessary (and too-often neglected). When dynamically linking modules with globals, the composed system might not be thread-safe even if the two independent modules tested in dozens of different contexts were safe. Namespace pollution -- Global names are available everywhere. You may unknowingly end up using a global when you think you are using a local (by misspelling or forgetting to declare the local) or vice versa. Also, if you ever have to link together modules that have the same global variable names, if you are lucky, you will get linking errors. If you are unlucky, the linker will simply treat all uses of the same name as the same object. Memory allocation issues -- Some environments have memory allocation schemes that make allocation of globals tricky. This is especially true in languages where "constructors" have side-effects other than allocation (because, in that case, you can express unsafe situations where two globals mutually depend on one another). Also, when dynamically linking modules, it can be unclear whether different libraries have their own instances of globals or whether the globals are shared. Testing and Confinement - source that utilizes globals is somewhat more difficult to test because one cannot readily set up a 'clean' environment between runs. More generally, source that utilizes global services of any sort (e.g. reading and writing files or databases) that aren't explicitly provided to that source is difficult to test for the same reason. For communicating systems, the ability to test system invariants may require running more than one 'copy' of a system simultaneously, which is greatly hindered by any use of shared services - including global memory - that are not provided for sharing as part of the test. The real issue will come when you try to track down bugs and it becomes a nightmare to figure out what's going on with those globals. Their values can be changed at any point by anything! That will cause bugs that will be hard to track. 100% promise that. I don't mean to be a snob about that but many people on many projects have experienced this which is why we get the globals are evil idea. Google "globals are evil" and see all the posts about it. Programming around globals will generally lead to easier code to read, maintain, & test. If you are used to coding without globals it can be hard to see how to do it so I'm willing to help if you like.
  23. If you tell me what you are specifically trying to do I can share how to avoid globals. Statics are the same thing as globals. LE follows some styles that aren't desired but game engines sometimes have to break the laws.
×
×
  • Create New...