• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

ZsjaWkaos

Members
  • Content count

    12
  • Joined

  • Last visited

Community Reputation

171 Neutral

About ZsjaWkaos

  • Rank
    Member
  1. What are you going to bring to the table? You either need to be a valuable member yourself or fund the rest of the team. I'm just asking out of curiosity because you haven't shared any info about yourself.
  2.     You're probably better off writing your own noise function if you want that amount of control. The problem is both with the perlin noise and the island mask. Some fixes that make it a bit better: //Little program to generate test map with only 0 and 1 tile #include <iostream> #include <noise/noise.h> #include "noiseutils.h" #include <stdlib.h> #include <string> #include <sstream> #define MAP_SIZE 512 using namespace std; using namespace noise; template <typename T> string tostring (T v) { ostringstream ss; ss << v; return ss.str(); } void generate_island(int iseed) { module::Perlin myModule; myModule.SetSeed (iseed); utils::NoiseMap heightMap; utils::NoiseMapBuilderPlane heightMapBuilder; heightMapBuilder.SetSourceModule(myModule); heightMapBuilder.SetDestNoiseMap(heightMap); heightMapBuilder.SetDestSize(MAP_SIZE, MAP_SIZE); heightMapBuilder.SetBounds(2.0, 6.0, 1.0, 5.0); heightMapBuilder.Build(); float islandMap[MAP_SIZE][MAP_SIZE]; srand(iseed); for (int count = 0; count < 1; count++ ){ //Initialize values for a new map for (int i = 0; i < MAP_SIZE; i++) { for (int j = 0; j < MAP_SIZE; j++) { islandMap[j][i] = 0; } } //Choose a random location, travel in random directions int x = 0, y = 0; int sx = 0, sy = 0; int size = MAP_SIZE / 2; int distance = 0; for (int i = 0; i < 1000000; i++) { int dx = x - sx; int dy = y - sy; distance = dx * dx + dy * dy; if((y > MAP_SIZE - 1) || y < 0 || (x > MAP_SIZE - 1) || x < 0 || distance > 5000) { x = rand() % size / 2 + rand() % size / 2 + MAP_SIZE / 2 - size / 2; y = rand() % size / 2 + rand() % size / 2 + MAP_SIZE / 2 - size / 2; sx = x; sy = y; } ++islandMap[x][y]; switch(rand() % 4) { case 0: ++x; break; case 1: --y; break; case 2: --x; break; case 3: ++y; break; default: break; } } //find max value for normalizing for (int i = 0; i < MAP_SIZE; i++) { for (int j = 0; j < MAP_SIZE; j++) { islandMap[i][j] = islandMap[i][j] * 2 - 1; } } int max = 0; int min = 0; for (int i = 0; i < MAP_SIZE; i++) { for (int j = 0; j < MAP_SIZE; j++) { if(max < islandMap[i][j]) { max = islandMap[i][j]; } if(min > islandMap[i][j]) { min = islandMap[i][j]; } } } //Multiply values of original by new maps generated for (int i = 0; i < MAP_SIZE; i++) { for (int j = 0; j < MAP_SIZE; j++) { float islandValue = (islandMap[i][j] - min) / (max - min); float mapValue = (heightMap.GetValue(i, j) + 1) / 2; float newValue = 2 * islandValue * mapValue - 1; heightMap.SetValue(i, j, newValue); } } } utils::RendererImage renderer; utils::Image image; renderer.SetSourceNoiseMap (heightMap); renderer.SetDestImage (image); renderer.ClearGradient (); renderer.AddGradientPoint (-1.0000, utils::Color ( 0, 0, 255, 255)); // shallow renderer.AddGradientPoint (-0.9701, utils::Color ( 0, 0, 255, 255)); // shallow renderer.AddGradientPoint (-0.9700, utils::Color ( 0, 128, 255, 255)); // shore renderer.AddGradientPoint (-0.9690, utils::Color ( 0, 128, 255, 255)); // shore renderer.AddGradientPoint (-0.9689, utils::Color (240, 240, 64, 255)); // sand renderer.AddGradientPoint (-0.9601, utils::Color (240, 240, 64, 255)); // sand renderer.AddGradientPoint (-0.9600, utils::Color ( 32, 160, 0, 255)); // grass renderer.AddGradientPoint (-0.4991, utils::Color ( 32, 160, 0, 255)); // grass renderer.AddGradientPoint (-0.4990, utils::Color ( 0, 0, 0, 255)); // pines renderer.AddGradientPoint (-0.4987, utils::Color ( 0, 0, 0, 255)); // pines renderer.AddGradientPoint (-0.3986, utils::Color (96, 63, 0, 255)); // dirt renderer.AddGradientPoint ( 0.0000, utils::Color (96, 63, 0, 255)); // dirt renderer.AddGradientPoint ( 0.0001, utils::Color (128, 128, 128, 255)); // rock renderer.AddGradientPoint ( 1.0000, utils::Color (128, 128, 128, 255)); // rock renderer.EnableLight (); renderer.SetLightContrast (3.0); renderer.SetLightBrightness (2.0); renderer.Render (); utils::WriterBMP writer; writer.SetSourceImage (image); writer.SetDestFilename ("tutorial" + tostring(iseed) + ".bmp"); writer.WriteDestFile (); } int main() { for(int i=0; i<10; ++i){ generate_island(i); } return 0; } The island mask consists of many random walks added together. The random walks scale poorly with size of the map (change the MAP_SIZE to see for yourself) because they tend to diverge very quickly. With the above code I've applied two methods two remedy this a bit: Terminate any random walk if they get beyond a certain distance away from their origin. Make the starting point of any random walk more likely to be in the middle with a triangular distribution and within a smaller region (controlled with the 'size' variable). Play a bit with the numbers to see if you can improve the results.   If you want to try something else try this instead: http://en.wikipedia.org/wiki/Diamond-square_algorithm If you set the first N levels yourself instead of randomly generating them you get much more control over the final output.
  3. The algorithm used looks like the same from: http://breinygames.blogspot.nl/2012/06/generating-terrain-using-perlin-noise.html   Just playing around a little (I did change some code so I could more easily read it), here is what I came up with: //Little program to generate test map with only 0 and 1 tile #include <iostream> #include <noise/noise.h> #include "noiseutils.h" #include <stdlib.h> #include <string> #include <sstream> using namespace std; using namespace noise; template <typename T> string tostring (T v) { ostringstream ss; ss << v; return ss.str(); } void generate_island(int iseed) { module::Perlin myModule; myModule.SetSeed (iseed); utils::NoiseMap heightMap; utils::NoiseMapBuilderPlane heightMapBuilder; heightMapBuilder.SetSourceModule(myModule); heightMapBuilder.SetDestNoiseMap(heightMap); heightMapBuilder.SetDestSize(512, 512); heightMapBuilder.SetBounds(2.0, 6.0, 1.0, 5.0); heightMapBuilder.Build(); float islandMap[512][512]; srand(iseed); for (int count = 0; count < 1; count++ ){ //Initialize values for a new map for (int i = 0; i < 512; i++) { for (int j = 0; j < 512; j++) { islandMap[j][i] = 0; } } //Choose a random location, travel in random directions int x = 0, y = 0; float previous = 0; for (int i = 0; i < 1000000; i++) { if(y == 511 || y == 0 || x == 511 || x == 0) { x = rand() % 512; y = rand() % 512; } if(previous >= islandMap[x][y]) { islandMap[x][y] += 1; } previous = islandMap[x][y]; switch(rand() % 4) { case 0: x -= 1; break; case 1: y -= 1; break; case 2: x += 1; break; case 3: y += 1; break; default: break; } } //find max value for normalizing for (int i = 0; i < 512; i++) { for (int j = 0; j < 512; j++) { islandMap[i][j] = islandMap[i][j] * 2 - 1; } } int max = 0; int min = 0; for (int i = 0; i < 512; i++) { for (int j = 0; j < 512; j++) { if(max < islandMap[i][j]) { max = islandMap[i][j]; } if(min > islandMap[i][j]) { min = islandMap[i][j]; } } } //Multiply values of original by new maps generated for (int i = 0; i < 512; i++) { for (int j = 0; j < 512; j++) { float islandValue = (islandMap[i][j] - min) / (max - min); float mapValue = (heightMap.GetValue(i, j) + 1) / 2; float newValue = 2 * islandValue * mapValue - 1; heightMap.SetValue(i, j, newValue); } } } utils::RendererImage renderer; utils::Image image; renderer.SetSourceNoiseMap (heightMap); renderer.SetDestImage (image); renderer.ClearGradient (); renderer.AddGradientPoint (-1.0000, utils::Color ( 0, 0, 255, 255)); // shallow renderer.AddGradientPoint (-0.9701, utils::Color ( 0, 0, 255, 255)); // shallow renderer.AddGradientPoint (-0.9700, utils::Color ( 0, 128, 255, 255)); // shore renderer.AddGradientPoint (-0.9690, utils::Color ( 0, 128, 255, 255)); // shore renderer.AddGradientPoint (-0.9689, utils::Color (240, 240, 64, 255)); // sand renderer.AddGradientPoint (-0.9601, utils::Color (240, 240, 64, 255)); // sand renderer.AddGradientPoint (-0.9600, utils::Color ( 32, 160, 0, 255)); // grass renderer.AddGradientPoint (-0.4991, utils::Color ( 32, 160, 0, 255)); // grass renderer.AddGradientPoint (-0.4990, utils::Color ( 0, 0, 0, 255)); // pines renderer.AddGradientPoint (-0.4987, utils::Color ( 0, 0, 0, 255)); // pines renderer.AddGradientPoint (-0.3986, utils::Color (96, 63, 0, 255)); // dirt renderer.AddGradientPoint ( 0.0000, utils::Color (96, 63, 0, 255)); // dirt renderer.AddGradientPoint ( 0.0001, utils::Color (128, 128, 128, 255)); // rock renderer.AddGradientPoint ( 1.0000, utils::Color (128, 128, 128, 255)); // rock renderer.EnableLight (); renderer.SetLightContrast (3.0); renderer.SetLightBrightness (2.0); renderer.Render (); utils::WriterBMP writer; writer.SetSourceImage (image); writer.SetDestFilename ("tutorial" + tostring(iseed) + ".bmp"); writer.WriteDestFile (); } int main() { for(int i=0; i<10; ++i){ generate_island(i); } return 0; }      
  4. [quote name='Scienthsine' timestamp='1348420467' post='4982969'] Now, as others have said, if your really just wanting 'the number of solid tiles between two points' and your counting the tiles in red in the photo, then it is just the greater of the absolute of the difference in Y or X. (As defined by the outer loop in the algorithm.) [/quote] This algorithm wouldn't account for any missing tiles. Although it would speed it up greatly. Perhaps a switch can be implemented for people using slower computers.
  5. You can try to use [url="http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm"]Bresenham's line algorithm[/url]. Go from the source to the destination you can then count the number of solid tiles along the way.
  6. [quote name='WitchLord' timestamp='1317257416' post='4867020'] You don't have to modify the library to disable use of global variables. Just add a simple check after the compilation, e.g. [/quote] Neat! I'll check this out tomorrow, I didn't have time to code anything today. [quote name='WitchLord' timestamp='1317257416' post='4867020'] Why do you have to disallow the declaration of a local variable of the OP type? The script cannot assign an invalid value to it anyway. It would just initialize to null, which your code is hopefully treating anyway. [/quote] That would be great. Even if it's not checked at compile time it would be enough for me to use it. If I can get both techniques working like you described I'll be using AngelCode in my next project. Thanks for your patience and help.
  7. [quote name='WitchLord' timestamp='1317173348' post='4866658']For example it should be allowed to store the OP in a local variable, but not a global variable, it must not be possible to store the OP in a class member, unless the class itself is guaranteed to die after the function returns. I'm not sure how you expect AngelScript to control this.[/quote] A class with an OP shouldn't be stored globally. To make it easier I wouldn't mind simply disallowing all global variables (it's good design anyway) I think I can easily patch this in myself with the following code (in as_compiler.cpp, after line 6269): [code] if( found ){ Error( "ERROR: NO GLOBAL VARIABLES ALLOWED!", errNode ); return -1; } [/code] All state data between calls will then be stored outside of AS. This means that I'll be running a modified version of AS. I think making a better solution will require quite some work (disallowing classes with OPs to be stored in global variables) on your end and I don't want to deliver you any more work than necessary. Unfortunately, I'm still not sure how disallow the following AS code (any pointers willbe greatly appreciated): [code] void main() { SomeData some_data; some_function( some_data ); } [/code] While still allowing: [code] void main() { SomeData some_data = some_other_function(); } [/code] The "IsVariableInitialized" returned always "true" for the code I tested it with. I placed the following code right at the beginning/end of "asCCompiler::CompileVariableAccess" hoping that it would return false for the first case of "SomeData". [code] cout << " IsVariableInitialized" << name.AddressOf() << ", " << IsVariableInitialized( &ctx->type, errNode ) << endl; [/code] [quote name='WitchLord' timestamp='1317173348' post='4866658']Alternatively you can implement a proxy class [..] [/quote] This is an interesting alternative, I'll consider it. I'm not a big fan of runtime errors when they can be found at compile time. There is also a (small?) amount of additional overhead/complexity.
  8. Does this mean that passing a pointer around (as described in my first post) is an impossible thing to do in AS? Is there any chance that this can be added in a future release (I can take a look at it myself)?
  9. I've updated the C++ code as follows: [code] void zero_ptr( void* memory ){ cout << "zero_ptr" << endl; memory = 0; } /* ... */ r = engine->RegisterObjectType( "SomeData", sizeof( SomeData* ), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_PRIMITIVE ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( "SomeData", asBEHAVE_CONSTRUCT, "void f( )", asFUNCTION( zero_ptr ), asCALL_CDECL_OBJLAST ); assert( r >= 0 ); [/code] The AS code (this should not be allowed!): [code] void main( SomeData some_data ){ SomeData sd = SomeData(); } [/code] Unfortunately "zero_ptr" seems to be called very often instead of only for the construction of SomeData. I would like to raise an exception on the construction (or assignment) of SomeData because that shouldn't be possible. EDIT: Apparently this is also possible : [code] void main( SomeData some_data ){ SomeData sd; } [/code]
  10. The code is now greatly simplified, I hope it is also correct. [code] class SomeData{ public: int x; int y; int z; }; void print_some_data( SomeData *some_data ){ cout << "SomeData! " << some_data << ", " << some_data->x << ", " << some_data->y << ", " << some_data->z << endl; } /* ... */ r = engine->RegisterObjectType( "SomeData", sizeof( SomeData* ), asOBJ_VALUE | asOBJ_POD | asOBJ_APP_CLASS ); assert( r >= 0 ); [/code] Instead of "asOBJ_APP_CLASS" "asOBJ_APP_PRIMITIVE" also works. However, I'm not passing an AS primitive so I think this is the right way to do it. C++ pointer types are [url="http://stackoverflow.com/questions/146452/what-are-pod-types-in-c"]plain old data[/url] types and I'm passing by value so I think this code should be correct.
  11. [quote name='SiCrane' timestamp='1316870440' post='4865466'] Did you try just registering the pointer as a value type? [/quote] Thanks, I haven't thought of treating the OP as a value itself. Here is my current solution that seems to work: [code] class SomeData{ public: int x; int y; int z; }; void print_some_data( SomeData **some_data ){ cout << "SomeData! " << *some_data << ", " << (*some_data)->x << ", " << (*some_data)->y << ", " << (*some_data)->z << endl; } static void construct_ptr( void **ptr ){ } static void copy_construct_ptr( void **other, void **ptr ){ *ptr = *other; } static void destruct_ptr( void *ptr ){ } /* ... */ r = engine->RegisterObjectType( "SomeData", sizeof( SomeData* ), asOBJ_VALUE | asOBJ_APP_CLASS_C | asOBJ_APP_CLASS_DESTRUCTOR ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( "SomeData", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION( construct_ptr ), asCALL_CDECL_OBJLAST ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( "SomeData", asBEHAVE_CONSTRUCT, "void f( const SomeData &in )", asFUNCTION( copy_construct_ptr ), asCALL_CDECL_OBJLAST ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( "SomeData", asBEHAVE_DESTRUCT, "void f()", asFUNCTION( destruct_ptr ), asCALL_CDECL_OBJLAST ); assert( r >= 0 ); [/code] AS code is same as before. Interestingly it even does not allow the value to be assigned to a global variable (no copy constructor) but it does allow it to be passed around. The C++ is a bit more verbose than I hoped for because of the double pointer maybe that can be improved somehow. On the AS side everything looks exactly like I want.
  12. Here is what I would like to do: [list][*]pass an opaque pointer (OP) from C++ to a function written in AngelScript (AS)[*]not allow AS to keep a copy around after the function has returned[*]allow AS to pass OP around to other functions (either written in C++ and registered in AS or written in AS)[*]use different types for different OPs, AS must not be able to pass the wrong OP to a function![/list] The reasons for doing it this way are: [list][*]to decouple any data stored in the OP from AS as much as possible (AS must not have any knowledge about OP's implementation details)[*]to keep any interfacing with AS very basic and simple (no need for any "tricky" reference counting, just passing a pointer around)[*]to avoid overhead from garbage collecting (AS will only keep OP around for the duration of the function call)[/list] Here is my attempt but as I'm rather new to AS and after some trial and error I still didn't succeed (hence this post ). Code snippet for C++: [code] class SomeData{ public: void release(){ } }; void print_some_data( SomeData &some_data ){ cout << "SomeData!" << endl; } /* ... */ r = engine->RegisterObjectType( "SomeData", 0, asOBJ_REF | asOBJ_SCOPED ); assert( r >= 0 ); r = engine->RegisterGlobalFunction( "void print_some_data( const SomeData &in )", asFUNCTION( print_some_data ), asCALL_CDECL ); assert( r >= 0 ); r = engine->RegisterObjectBehaviour( "SomeData", asBEHAVE_RELEASE, "void f( )", asMETHOD( SomeData, release ), asCALL_THISCALL ); assert( r >= 0 ); [/code] Code for AS (test.as): [code] void main( SomeData some_data ){ print_some_data( some_data ); } [/code] I get the error. "test.as (1, 11) : ERR : Parameter type can't be 'SomeData'". I think it is because AS wants to create a new object SomeData but does not know how. However, I just want AS to keep the OP around and not do anything with it, except pass it to some functions. Is what I want to do possible in AS and if so [i]how[/i]? It seems like an incredibly simple thing to do yet I can't figure it out. Any help will be greatly appreciated!