Tac-Tics

Members
  • Content count

    447
  • Joined

  • Last visited

Community Reputation

197 Neutral

About Tac-Tics

  • Rank
    Member
  1. Learning LISP

    Paul Graham is a nut. He did well in the .com bubble and he let it really go to his head. His books might be worthwhile, but he's a fanatic elitist and you should take everything he says with salt. The Little Schemer is an interesting book, but the format gets very irritating after a while. I read it after the whole concept of lisp "clicked", so maybe it's better when the ending is a surprise. The absolute best book on LISP is "SICP" (Structure and Interpretation of Computer Programs). It was the old MIT textbook for programming 101. It uses a minimal Scheme dialect. The last two chapters are devoted to the interpreter (they call it the "metacircular evaluator") and a full-fledged LISP compiler that compiles LISP to an assembly language DSL which is also written in LISP. You can find cheap library resell copies on eBay. The SICP lectures are also online: http://groups.csail.mit.edu/mac/classes/6.001/abelson-sussman-lectures/ Just a few tips overall about Lisp. Common lisp is the world's second oldest language. Even though it is a "functional" language, the standard CL libraries do very weird shit. The CL community (especially #lisp on freenode.net) are kinda assholish. Scheme is an academic language. It's small and easy to learn, but it has crappy library support. Clojure is a modern lisp. If you want to do anything with Lisp seriously, I would suggest you start there: http://clojure.org/
  2. Game Controls and Logic Question

    [quote name='Master Jake' timestamp='1306688064' post='4817153'] I would think it appropriate to separate the window control stuff from the actual game logic (e.g. separating the code that checks for mouse clicks from the code that actually moves the player to the location that you clicked the mouse). [/quote] Separating logic out is an important part of good software engineering. It's great you picked up on that need. Of course, usually the way it works is you start off writing a Horrible Mess, then later (but not too much later) you go through and separate it out. If you're inexperienced, you probably want to start this way. Worrying about architecture before you can "play" your first game is usually a Bad Thing. [quote]I've yet to figure out a way to do this without using a ton of globals (or by faking globals through using static class singletons).[/quote] One thing I didn't understand for a long time was why you should avoid globals. All programs are taught that globals and singletons are a sin against mankind, but the actual [i]lesson[/i] to be learned is omitted from the lecture. My advice: use globals and/or singletons where you feel you need to. There will come a point where one of two things will happen: 1) You will forget where something is declared, or 2) You will want two instances of something that there is (by definition) only one copy of. Both can be fixed. How hard it is to fix it depends on how proliferated the problem is in your code. One important lesson often omitted is that EVERY application eventually references a singleton. You eventually want to reference THE screen, THE database, THE network, THE sound subsystem, etc. It's helpful to have those things loosely coupled for testing (talking to a mock database, for example), but in an actual application, there's only going to be one of each of these things in existence. Ever. So, it's perfectly fine to make them singletons. Keep in mind the cost of making something local (as opposed to global) is that you are responsible for keeping track of it. You always either have to pass a reference to it or some object which keeps a reference to it. This kind of plumbing can be its own nightmare to manage. In terms of events, what you probably want is two layers of events. You have UI events (mouse clicks and keyboard inputs) and you have game events (move commands, attack commands, etc). Then, at the top level of your program, your job is to translate UI events into game events and pass them to your game's event loop. From the event loop's perspective, all it does is expose one callback ("sendEvent"), and other than that, all it knows about are events. The UI, on the other hand, knows how to create a game event and how to send it (using "sendEvent"), but it doesn't know what the events mean past what creates them. So as far as defining a class hierarchy, if it were me, I'd create a singleton game event loop, give it a sendEvent() method, then have the UI callbacks (onMouseClick() or whatever) create game events and send them via GameLoop::singleton()->sendEvent(...). There's no real need for inheritance here. (Though I'm sure you could find another good architecture that uses it well). If you have a setup like this, and you need to swap out the UI component (say you're porting your game to a console system or a smartphone platform), you just need to rewrite the UI with whatever toolkit is at your disposal (provided by iOS or PS SDK or whatever). As long as you keep most of the game logic in the event loop, you don't have to rewrite very much at all.
  3. The real lesson to be learned is that projects are always a LOT more work than they seem. You start off with a game with space ships. You give them the ability to fly around, each one has armor points and gun attributes. You're done, right? What about the art? Not even the actual image files, but the graphical design overall. How big are the images compared the the screen? What formats do you keep everything in? If your sprites are animated, how many frames? How do you control their animation cycle? What about other graphical effects? What about the user interface? Have you done menuing? How do you handle the text for the menus. Do you have a menu system out of the box or do you have to write one? Does the game have an options screen? What options are available? Graphics? Sound? Do you have a high score? How does the player enter their high score? When do players see the high scores? Is all that done? Great, your engine is done. How do you create levels for the game? Oh, crap, I forgot about levels. Does the game support progression between levels? How is that indicated to the player? How is the transition between levels done? (Cut screen? Just everything abruptly stops and the new level loads?.... (Oh yeah, what about loading screens?)). So level editor, crap, that's an entirely different program to write. What menu options are needed for that? How do you place objects on the screen? How do you do all this AND make it fun? That's the last 10% of your game. The devil is always in the details. And not just for games. For every project of any kind you'll ever do in life. It's better to start off working with more experienced people than to try and launch your own project. You will learn a lot from working with other people that you can't really teach in school. Things like: * How to deal with problem people. * How to spot scope creep and identify critical features. * How to track and handle issues that come up. * How to persevere when problems seem insurmountable. In addition to a major long term project, there is nothing at all wrong with dabbling. If you want to try writing a toy compiler, game mock up, website, or play with a new language or API, do so. But don't commit to it and don't trick yourself into thinking it's a long-term thing. Learn and move on.
  4. "Slow" 2D Arrays

    Quote:Original post by phresnel Though that is not standards compliant, Yeah, but it will work in any modern C compiler. You could also just define a Vertex as an alias for float[3]. Vertex[n] is more meaningful than float[3][n].
  5. Clarify pointers?

    Quote:Original post by nobodynews Quote:Original post by Tac-Tics Quote:Original post by nobodynews It's the same in Java, references are passed by value. There is no pass by reference in Java.I didn't say this, I assume it was a copy-paste mistake somewhere. Whoops, sorry about that. That should have been DevFred. Apologies. Quote:Original post by DevFred Wrong. There is no pass by reference in Java. This article is arguing semantics. What exactly IS the object you're manipulating? What do you care about in your code? A Foo? Or a reference to a Foo? Depending on your answer, there are two interpretations. If you're talking about manipulating Foos, you pass by reference. If you're talking about manipulating references to Foos, you pass by value. Like I said, it all boils down to pass by value in the end. Every reference parameter must ultimately be turned into copying a pointer. So every language is "pass by value" in a meaningless sense. Quote:Original post by Whatz Click here to follow this "pointer" to an article about pointers URLs are excellent examples of pointer :) Don't send your friend the HTML code for the page, send them the URL. Hell, sometimes the URL is too long, so you encode it as a tiny URL, which is a pointer-to-a-pointer.
  6. Clarify pointers?

    Quote:Original post by jpetrie This is just an implementation detail; it's not behavior described by or mandated by the standard (relevant chapter is 5.2.5). True, but it is nevertheless a valid use for pointers, which was part of the OP's question.
  7. Are 0 pointers unsafe?

    In C++, 0 is polymorphic. It can take on any integral type, be it a byte, a word, a doubleword, or a quadword. Even if you did something retarded like Obj* ptr = (char) 0, the value would still be coerced correctly to a quadword by the compiler.
  8. Clarify pointers?

    Quote:Original post by nobodynews I can't speak for Java, but C# actually passes references by value by default. In C#, by default, objects created from classes are passed by reference and objects created from structs or primitives are passed by value. The ref keyword works just like the reference operator in C++. The tricky part about ref is when you use it on a reference-type object, you get a reference-to-a-reference. To make a better analogy, a reference-to-a-reference is like giving someone the page and line numbers that their phone number appears on in the phone book. Quote:Quote:* Structs. Behind the scenes, structs are actually implemented with pointers, exactly the same as arrays! On the stack neither are implemented with pointers. You misunderstood me. When you have a struct like this: struct Coordinate { int x; int y; int z; } The block: Coordinate c; c.x = 1; c.y = 2; c.z = 3; Will get translated to this: Coordinate c; *(&c + 0) = 1; *(&c + 4) = 2; *(&c + 8) = 3; (Slight abuse of notation, so that pointer arithmetic assumes the datasize is 1 byte). Of course, that's handled internally in the compiler, but the point stands: an element of a struct is the dereferenced value of pointer plus an offset. Quote:Original post by nobodynews It's the same in Java, references are passed by value. There is no pass by reference in Java. I'm not talking about passing the references. I'm talking about passing the objects. In the end, everything is passed by value, be it the actual object or a reference to the object. In Java, all objects are passed by reference. All primitive types (ints, booleans, etc) are passed by value. In languages like Python and Ruby, even ints and booleans are passed by reference -- but they are immutable objects in those languages, so no changes can propagate up the stack anyway, because no changes to those objects are ever allowed. So from the programmer's viewpoint, they work very similarly to Java.
  9. Clarify pointers?

    The real problem with pointers is that you don't really need them in C++. They are the blood of C, but C++ supports references, which diminishes their usefulness. It's easiest to understand pointers if you're working in pure C. Your computer, at a fundamental level, only understands two datatypes: integers and floats. Everything in your computer is an integer or a float. All operations (arithmetic, logic, copying, etc) work only on these two types. In C, you can create more complex data types using structs. A struct allows you to group a number of integers and floats together. This is convenient for the programmer because we only have to keep track of one object instead of all its parts. (You drive your "car"... you don't drive your "chassis, motor, seats, dashboard, windshields... etc"). The first obvious problem comes about with functions. Functions in C are pretty naive. You can only pass integers and floats to a C function[sup]1[/sup]. When you pass an integer or a float to a C function, it copies the value onto the stack[sup]2[/sup]. If you were to pass a structure, it would need to copy the whole structure to the stack. This can't be done in a single operation by the underlying hardware, and so C disallows it. (Remember, C was considered to be unreasonably slow when it first came out). So if passing a structure is disallowed, how do you pass it? The answer is you don't copy the struct to the stack. You copy a pointer to the struct. A pointer is just an integer with a special operation: it can be dereferenced (or "followed"). And since a pointer is just an integer, it can be passed as usual. Let's talk about dereferencing. What does that even mean? A real-world analogy would be calling someone's phone number. When you make a new friend, they might give you their phone number. They scribble it down on a piece of paper and you slip it in your pocket. (The person is the structure. The phone number is the pointer.) Later, if you want to know their birthday, you can call them on the phone and ask. (To call the number is to dereference the pointer). An absurd alternative would be: you make a friend, he CLONES himself. You take the clone home with you. And later, if you wanted to know his age, you could just ask him (without calling him). Given you had the power to clone somebody, both solutions are viable. The first option, though, is undoubtedly easier. There is one other small difference. When you clone someone, the clone and the actual person need not be in sync. If the clone breaks his leg, the actual person will not feel it. If you see the clone has a broken leg, it doesn't tell you anything about how your actual friend is doing. This phenomenon -- that changes to the cloned person don't affect the original -- is the essence of pass-by-reference versus pass-by-value. The telephone number scenario is pass-by-reference. The clone is pass-by-value. Both are useful in different circumstances. In particular, Pass-by-reference, is useful for communicating to the caller. C only supports one return value (and again, it has to be an integer or a float). But what about functions that need multiple return values? The most common solution is to pass in extra parameters by reference, and then modify them in the function. After the function returns, the modifications have taken place on the actual object (not on a clone), so in effect, you have passed information from the function to the caller. Pointers are actually used "under the covers" for a lot of programming techniques. In modern languages, the use of pointers is almost completely invisible. But never-the-less, they play a huge part in everything you do. (C++ is a weird language because it covers up many uses of pointers while leaving other users exposed.) Some things you may not have known pointers are used for: * Passing by reference (see above). This includes "reference paramters" in C++ and how all objects are passed in Java. Most dynamic languages (Python, Ruby) pass exclusively by reference. Even if those languages don't expose pointers, that is always how they are implemented. * Dynamic memory allocation. In C, when you declare a variable, space is allocated on the stack for that variable. The downside of this is that those variables are destroyed when the function returns. When you want an object to live longer than the function that creates it, the usual technique is to allocate the memory on the heap with malloc (new in C++). Malloc returns a pointer to an area of memory and says "ok, you do what you need to do with this memory, but remember to call free (delete in C++) when you're done with it!". * Arrays. In C, arrays are just a thin veil over pointers. A char[] is essentially the same data type as char*. When you do str[i], you can always rewrite it as *(str + i), which means "dereference the value that's i addresses down from str". * Structs. Behind the scenes, structs are actually implemented with pointers, exactly the same as arrays! One final use of pointers that is way beyond the need of game programmers is hardware manipulation. The way most computers interact with hardware is through "memory mapped IO". What this means is that certain addresses in memory don't manipulate your RAM, but instead, are linked to IO devices. For example, there is a block of memory which directly affects your video card (although, only your OS has access to this memory). Without pointers to directly manipulate specific regions of memory, there would be no IO ;) I hope that helps a bit! [sup]1[/sup] - This is not true in modern dialects of C, but I don't know of any C library that uses this functionality. [sup]2[/sup] - This is not strictly true for floats on x86, but it's conceptually equivalent to what I said.
  10. All of programming! Need Overview

    Troll programming.reddit.com for a few hours a day for the rest of your career. Programming is so vast it can't possibly contained in one book or tutorial. It takes a whole Internet to learn how to program. Designing large programs is a struggle. Large programs aren't good programs, because as the size increases, the complexity of a system begins to explode. Large programs are ugly. They are buggy. They are not fun at all to work with. When you work on a large project, the biggest issue you face is figuring out how to organize everything. This is essentially what "system architecture" is all about. If you ever see a system architecture book, there is nothing about code anywhere inside. But to be sure, it all boils down to how to find a "home" for every class you write in Java or C#. Much of learning strengths and weaknesses is learning the tools yourself. I can tell you XML is a shitty, shitty format, and I could rant on about why it is. But you can't really understand why it is until you feel the pain of working with it first hand. On the other hand, you may have used XML before. You may have enjoyed it, and enjoyed what you could do with it. You might not understand why I have such a negative opinion when yours was so great. In that case, it's because you don't have experience with other tools to use as a baseline. Maybe you haven't used JSON, which is much more elegant. Maybe you haven't had to work with other people's custom, bloated XML configuration files as much as I have. Maybe you haven't had the problems I have where someone in your company is hand-editing XML files and neglecting to properly close tags. You have to learn these things through experience. Most common programming tools are free, so there's no reason other than lack of time or motivation not to play with them. Learn a new language every year and learn it well. Write tools that make your life easier. Over time, your ability to foresee the important details in a program will grow, and you will be able to write larger programs with greater ease. One other piece of advice: join an open source project. Find a tool you can be really passionate about. It could be an application, an OS or kernel, a library, a programming language, a tool, a server, or whatever. Then try to break into the community. Read through the source code. Don't worry about the details of how every function works -- just concentrate on the overall architecture. Ask on the mailing list for an easy bug to fix from their bug tracker database. Do your best to solve the problem. Write a patch for the bug. Submit it. It will come back to you and they will tell you why it's wrong. Then go back and try and account for what they told you. All you have to do is spend enough time looking at the code and asking yourself questions about how it might work, and soon enough, it will all make sense.
  11. Learning Guidance

    Quote:Original post by gamby ...DeVry isn't a great school and is laughed at, true?... A school like Devry doesn't look as good on a resume as a traditional university. I can't attest to the quality of classes there, but curriculums vary widely between different schools. A good technical school will get you a better education than a shitty traditional school. So don't become discouraged. Regardless of where you go to school, most of what you need to know to write games has to be learned independently. There is just so much to learn. It's more than "knowing DirectX whatever". A pianist has all the notes he can play laid out before him, but it still takes a decade to become a musician. Similarly, you could know every single part of the OpenGL standard and still have trouble putting together a game. For reference, it's not "DOS". DOS was the OS your computer ran in 1990. What you are programming for is called a "terminal" or a "console". Don't call it DOS :P Asteroids would be a great start. My suggestion would be to learn SDL, a library written in C that provides a very simple window and rendering API (and also supports OpenGL).
  12. Web Programming

    Quote:Original post by kaktusas2598 So, i wanna ask, what languages it will be useful to learn for creating web sites? Absolute base requirements for web programming are HTML, CSS, and javascript. These are the languages every web page is written in. HTML describes the layout. CSS describes the styling. When a web page is loaded by your browser, it parses the HTML and CSS and creates an in-memory object called the DOM (Document Object Model). The DOM is a tree structure describing the entire page. When the browser displays your page, it does so by walking over each node in the DOM and rendering it according to its type and properties. javascript allows you to inspect and modify the DOM after a page has been loaded. A "static" HTML file will have a set number of everything: forms, images, links, table rows. But you can add forms, change image sources, change where a link points to, add or remove table rows, etc. by using javascript. javascript also has access to other important APIs provided by your browser. For example, in javascript you can: * Create, read, update, and destroy (CRUD) cookies, which are very small data stores stored in the browser itself (as opposed to in your database). * Send asynchronous messages back to the server and receive the reply. This is called AJAX or XMLHttpRequest, but it's a bit poorly named, as there is no requirement to use XML. JSON and other textual data formats work just as well. * Render to <canvas> objects (Only in HTML 5) These three technologies are collectively the "client side" half of web development. The other half is the "server side". The server is responsible for generating and sending the necessary HTML, CSS, and javascript over the Internet. There are many techniques for doing this. Generally speaking, you can use any programming language you want. You can write a site in C++, C#, Python, Ruby, Java. There are a number of standard frameworks for writing web pages, but perhaps the easiest one to understand is CGI. CGI is a very simple standard for writing web applications in the early days of the web. The premise is drop-dead simple. A CGI-capable web server (pretty much every web server ever written) receives a request. It takes the request and finds the corresponding CGI program. It executes the CGI program (which might be a C++-generated binary or a Perl script or whatever) and it executes it. Any data the web server wants to share with the program is send through environment variables. The standard output of the CGI program is redirected to the client's socket. So sending HTML to the browser is as simple as 'cout << "<html><body>Hello world!</body></html>";' CGI isn't used all that much today for serious applications. The problem with it is that it launches a new system process for every request. Newer frameworks such as FastCGI, mod_php, or Java servlets reuse old processes, which means they will be much faster. Still, for learning, CGI is a good tool to use. Developing web applications is hard. The core web technologies were developed over a long period of time by a large number of people who were all in competition for market share. The result is that the technologies tend to suck badly. HTML was written when memory was still measured in kilobytes. CSS has an extremely limited model for positioning HTML elements. It wasn't until 2 years ago Internet explorer finally decided to comply with W3C standards. I can't blame them, though, because W3C's standards are abysmal. New web technologies take a long time to gain acceptance on all browsers. Even now, I don't believe <canvas> is supported on IE, but it's been around for over a year on Firefox. No two browsers display the same web page the same way. On top of that, because of the .COM boom and the easy of distributing web-based applications, everyone and their mom has tried their hand at making a website. The result is that the web development industry is swamped with amateurs and people who generally don't know what the fuck they are doing. Security. It's a big thing on the web. When you expose your system to the entire Internet, everyone in the world has an opportunity to break your shit. If you're writing for a business, a determined individual abusing a single vulnerability could potentially bankrupt your company. There could be vulnerabilities at every level of your technology stack: in your web server, in your database server, in your encryption layer, in your compiler, in your web framework, in your application, in your client-side design. So bottom line: learn the most common vulnerabilities. Know what SQL injection is. What cross-site scripting is. Don't use C++ to write web apps. Keep a full backup of your code and your database in a separate place untouchable by your main server. Salt all passwords you store. Never send passwords by email. Don't use PHP.
  13. "2D Projection"

    You project a 3D scene onto a 2D screen. Part of the meaning of the word "projection" is the reduction in the number of dimensions. When you project a 2D scene, you're left with a 1D line. It looks a little like you just want to do a simple viewport transformation. In 2D, you probably want to keep your camera axis-aligned and prevent it from rotating. The height and width of the viewing rectangle is determined by the screen you're drawing to. All that's left is specifying the position of the viewing rectangle, which can be done with a single (x, y) coordinate.
  14. Quote:Original post by gasto Thanks for the explanation. I know that there are stackless languages, like stackless Python, how they work is a mistery. Python *does* use a stack. There is a variation of Python called Stackless Python, though, which does not rely on the same mechanism for function calls (just as Konfucius said). But regular CPython, as well as many other flavors (Unladen Swallow, PyPy, JPython, IronPython) all use a stack. The stack frame model isn't the only model of computation, mind you. It's just the most common. One advanced language construct available in functional languages is the continuation. A continuation is like a goto on steroids. I won't get into an explanation here (because they aren't available in C++ or C# or any of the languages people normally use for games). But one trait continuations have is they allow you to write programs where the stack frames form a tree instead of a stack. With continuations, you can pause execution on one function and jump to another. For something that's half way between these two are languages that support closures (Python... sorta, Ruby, javascript, Lua). Because closures can capture references to variables on the stack, those variables need to continue to exist even after the function for that stack frame returns. Of course, for games and 90% of programming, you don't need to worry about any of that :) The stack is the hammer of your programming toolbox. It's simple, it doesn't solve every program, but every craftsman should master it.
  15. You have a program. It consists of functions. At any point, execution is "inside" a function (determined by the process's program counter). A function can call another function. When this happens, execution changes to be inside of the called function. A function can return to the point where it was called and resume execution there. Therefore we need to keep track of which functions call which. To add one last detail, a function has the option to call itself (we call this a recursive function), so it is possible to have two "copies" of the same function being executed at different points. This is the scenario we're dealing with (slightly simplified, because things like threading make it a little more complicated). The technique we use to handle this is called a stack frame (also called an activation record). Whenever a function is called (including the main function in a program), we create a new stack frame. The stack frame is a kind of bookkeeping for function calls. Typically the stack frame contains: * the return address - the address of the instruction immediately following the function call that created this stack frame. * the parameters - the actual parameters passed to the function are copied to the stack frame. * scratch space - memory reserved for the callee. This is where local variables are stored. When you call a function, the stack frame is created with this information and pushed onto a stack. The program counter then jumps to the function's address in memory, and the new function continues. The function may access local variables by inspecting the stack frame. The function may also use the scratch space to store any local/temporary variables it needs to do its job. When the function needs to return to its caller, it simply grabs the return address from the stack frame, pops the stack frame, and then jumps to that address. Under this model, functions are always properly nested. They always know who called them. They have access to their own copy of the parameters and they have space to work with temporary variables. It's all very nice :) This is pretty much all there is to what you call "stack memory" as you call it. Global data is much, much simpler. There's one copy of a variable for the whole program. It's not stored in any activation record. When you change it, it changes throughout your program -- whereas in contrast, changing a parameter only changes that value in the current stack frame. Because global variables are simpler, new programmers will tend to want to use them. The simplicity is nice for certain things, but stack-allocated variables are much more flexible for many tasks.