• Content count

  • Joined

  • Last visited

Community Reputation

329 Neutral

About Ravnock

  • Rank

Personal Information

  1. I have been working with GameSparks in the last months.   One thing I miss about their API is you can't query to the leaderboards something like "Hey, give me from that leaderboard a player that posted a value similar to 'x'"   I use leaderboards for matchmaking and to me this would be a very interesting feature.   You have the classic AroundMeLeaderboardRequest, but then you could get people too similar to you. With this "AroundValueLeaderboardRequest" (ok, maybe it's not the best name), your matchmaking could be more flexible, it may help to perform matchmaking with different difficulty levels.   The following event code achieves what I've just commented. It works better when the leaderboard is uniformly distributed, but if this is not your case, you can easily change the search for a dichotomic search.   Here is the code: //Retrieve the input parameters var lbShortCode = Spark.getData().lbShortCode; //leaderboard identifier var fieldName = Spark.getData().fieldName; //name of the field we are posting to the leaderboard var fieldValue = Spark.getData().fieldValue; //we are looking for a player with that value posted var numIterations = Spark.getData().numIterations;//number of iterations to try to improve the result var request = new SparkRequests.AroundMeLeaderboardRequest(); request.entryCount = 1; //This is the minimum: my preceding enemy, me and the next enemy request.includeFirst = 1; //To bound the search in the upper limit request.includeLast = 1; //Same for the lower limit request.leaderboardShortCode = lbShortCode; var response = request.Send(); var firstInLeaderboard = response.first; var lastInLeaderboard = response.last; var myScore = 0; var myRank = 0; var currentRank = 0; var currentScore= 0; var targetScore = fieldValue; var bestScore = firstInLeaderboard[0][fieldName]; //first is an array with a 'lonely' value var worstScore = lastInLeaderboard[0][fieldName]; //same than above var worstRank = lastInLeaderboard[0]["rank"]; //We will receive 3 values unless there aren't any people before or after me //...or if the leaderboard is empty if (response.data.length > 1) { myScore = response.data[1][fieldName]; myRank = response.data[1]["rank"]; } else { myScore = response.data[0][fieldName]; myRank = response.data[0]["rank"]; } var loops = 0; var topScore = bestScore; var bottomScore = myScore; var topRank = 1; var bottomRank = myRank; var done = false; var response = null; while (loops < numIterations && !done) { var rankDiff = bottomRank - topRank; var scoreDiff = topScore - bottomScore; if (rankDiff == 0 || scoreDiff == 0) { //there is no difference, our search has finished targetRank = topRank; done = true; } else { var scorePointsPerRankPosition = scoreDiff / rankDiff; if (scorePointsPerRankPosition <= 0) //I'm the best (or even better) scorePointsPerRankPosition = 1; var rankMovement = (topScore - targetScore) / scorePointsPerRankPosition; var targetRank = topRank; if (rankMovement < 1) { done = true; } else { targetRank = topRank + rankMovement; } if (targetRank > worstRank || targetScore < worstScore) { targetRank = worstRank; done = true; } } var request = new SparkRequests.LeaderboardDataRequest(); request.entryCount = 1; request.leaderboardShortCode = lbShortCode; request.offset = targetRank - 1; response = request.Send(); currentRank = response.data[0]["rank"]; currentScore = response.data[0][fieldName]; if (currentScore < targetScore) { //as we didn't reach the desired score we will limit the search //raising the bottom limit bottomScore = currentScore; bottomRank = currentRank; } else if (currentScore > targetScore) { //as we didn't reach the desired score we will limit the search //raising the bottom limit topScore = currentScore; topRank = currentRank; } else { done = true; } if (done) break; ++loops; } Spark.setScriptData("leaderboardData", response.data[0]); I hope you will find it useful or, at least, interesting. You can check for more stuff in my programming blog: http://davidorejuela.blogspot.com.es/
  2. This will allow you to share a pseudo random number generator between several users. To use it during  a Real time match you just have to send the request from your RT event. It needs a runtime collection to store the seed related to the current session, it's called "MatchSeed", that's completely managed from the following module, MODULE_ATOMIC_RANDOM. The module has functions to retrieve, update and remove the seeds from the collection. Just create a Cloud Code's Module and copy the following code. Edit: I have included the option of peeking the next random numbers: One interesting thing about pseudo random numbers is, given a seed, the sequence of random numbers is predictable, so you can know what are the next numbers in the sequence. I completely forgot to add the posibility of peeking the next numbers in my "Atomic, Peristent and Pseudo Random Number Generator". I've modified the event, adding one parameter "numPeeks". Now in the scriptData you have a key "numPeeks" with the numPeeks returned (is limited to 10 for security reasons) and one key per num peeked: "peek1", "peek2", and so on.  ///////////////////////////////////////////////////////// // File MODULE_ATOMIC_RANDOM ////////////////////////////////////////////////////////// function GetMatchSeed(sessionId) { var matchSeedCollection = Spark.runtimeCollection("MatchSeed"); var result = undefined; var matchSeed = matchSeedCollection.findOne({"sessionId":sessionId}); if (matchSeed != null && matchSeed != undefined) { result = matchSeed["seed"]; } return result; } function SetMatchSeed(sessionId, seed) { var matchSeedCollection = Spark.runtimeCollection("MatchSeed"); var query = { "sessionId": sessionId }; var newObject = { "sessionId": sessionId, "seed": seed }; var success = matchSeedCollection.update(query, newObject, true, false ); //upsert: true, multi: false return success; } function RemoveMatchSeed(sessionId) { var matchSeedCollection = Spark.runtimeCollection("MatchSeed"); var query = { "sessionId": sessionId }; var success = matchSeedCollection.remove(query); return success; } And here you have the event's code you need to get your Atomic,Persistent, Pseudo Random-Generator: require("MODULE_ATOMIC_RANDOM"); //Based on: http://stackoverflow.com/questions/521295/seeding-the-random-number-generator-in-javascript /* We pass an object because we want the changes on the seed to be an output parameter That way we can store the seed in a runtime collection and use it again when needed, keeping the sequence of random numbers from one event execution to another event execution.*/ var PseudoRandomSeed = function(obj) { return function() { //if peek true we will only look the value, but seed won't be modified var newSeed = Math.sin(obj.seed) * 10000; var result = newSeed - Math.floor(newSeed); obj.seed = newSeed; return result; }; }; var sessionId = Spark.getData().sessionId; var numPeeks = Spark.getData().numPeeks; //Mutex: We don't want other user to get a random while this is running Spark.lockKey("AtomicRandom", 100); var seedFromDB = GetMatchSeed(sessionId); var lastSeed = undefined; //If there is no seed get the session ID as the prime seed if (seedFromDB == null || seedFromDB == undefined) { lastSeed = parseInt(sessionId, 16); //I'm supossing the sessionID is an hexadecimal number } else //Otherwise, we used the stored seed { lastSeed = seedFromDB; } var myObj = { seed: lastSeed }; var PseudoRandom = PseudoRandomSeed(myObj); //Generate randomNumber and store it in the scriptData var randomNumber = PseudoRandom(); var setMatchSeedSuccess = SetMatchSeed(sessionId, myObj.seed); Spark.setScriptData("randomNumber", randomNumber); //Generate peeks for the next randoms if (numPeeks != null && numPeeks != undefined) { if (numPeeks > 10) //security check: Max peeks allowed is 10 numPeeks = 10; Spark.setScriptData("numPeeks", numPeeks); for (i = 0; i < numPeeks; ++i) { Spark.setScriptData("peek" + i , PseudoRandom()); } } Spark.unlockKey("AtomicRandom");  I hope you find it useful or interesting. Check my blog for more stuff: http://davidorejuela.blogspot.com.es
  3. Setting up a Vehicle

    Are you breaking and accelerating at the same time?          m_vehicle->applyEngineForce(gEngineForce,wheelIndex);        m_vehicle->setBrake(gBreakingForce,wheelIndex);
  4. What are the benefits of the TOI?

    What do you mean with TOI?
  5. Setting up a Vehicle

      You are updating the gEngineForce var in your code, this is right, but this var is never used elsewhere. I was checking the original btRaycastVehicle code and I think you should do something similar with that gEngineForce: apply it to the wheels:   void btRaycastVehicle::applyEngineForce(btScalar force, int wheel) 383 { 384  btAssert(wheel>=0 && wheel < getNumWheels()); 385  btWheelInfo& wheelInfo = getWheelInfo(wheel); 386  wheelInfo.m_engineForce = force; 387 }
  6. Setting up a Vehicle

    Is your Vehicle a child class of btRaycastVehicle? Could you post the cpp and header file?
  7. Setting up a Vehicle

    engineForce is never used, am I right?   I think you should override the updateVehicle virtual function
  8. Hi Mekuri   I don't understand why do you want to update only some random tiles, but this could be what you want:   int numTilesToUpdate = ...;   for (int i=0; i < numTilesToUpdate; i++) {     m_Tiles[rand()%m_Tiles.size()].Update; }
  9. The Problems about the FPS Camera

      From Wikipedia (general case): For n greater than 2, multiplication of n×n rotation matrices is not commutative.   http://en.wikipedia.org/wiki/Rotation_matrix Hi, Ravnock, thanks for your reply. I don't know where is wrong in my above inference.hope someone can pinpoint it to me.   I have not idea about OpenGL but I use to build my rotation matrix with the D3DXMatrixLookAtRH function, I think gluLookAt it's similar. You set where you are, where are you looking at and the up axis, for a FPS is everything you need...
  10. The Problems about the FPS Camera

      From Wikipedia (general case): For n greater than 2, multiplication of n×n rotation matrices is not commutative.   http://en.wikipedia.org/wiki/Rotation_matrix
  11.   There was another discussion about copyrights here http://www.gamedev.net/topic/544351-can-you-give-away-free-remakes-of-old-games/ (very polemic, indeed and with opposite opinions), for example:   Names, ideas, concepts and techniques cannot be copyrighted, in other words, the actual game aspect of a game cannot be copyrighted. I don't know why people are implying otherwise to be honest. The parts of a game that can be copyrighted are sounds (sound effects and music), graphics (photographs, icons, fonts, sprites, etc), literature (instructions, dialogs, etc) and cutscenes. So you can recreate Pacman without copyright issue provided you don't use the same sound effects and sprites (or sound effects and sprites that have been derived from the originals). If you make brand new sprites and brand new sound effects then you're fine. Though you might not really consider it to be a Pacman clone by then perhaps.   This another website speak about that:   http://www.newmediarights.org/guide/legal/Video_Games_law_Copyright_Trademark_Intellectual_Property%20
  12. Hi all,   I am developing a tool for my game project, and I want to have the "find" feature. When Ctrl + F is pushed I want to create a new window. (I don't want to have a dialog, I would like to implement the find feature with a window and a embedded dialog inside, VS 2008 style)   The window is a member variable in my class, m_FindWindow and this is my OnCreate method   Whatever::OnCreate(LPCREATESTRUCT lpCreateStruct) { ...     if(m_FindWindow->GetSafeHwnd() == NULL) { if (!m_FindWindow->CreateEx(WS_EX_STATICEDGE, _T("STATIC"), _T("Find"), WS_VISIBLE|WS_CHILD|WS_TABSTOP|LVS_REPORT|LVS_SINGLESEL|LVS_SHOWSELALWAYS|LVS_NOCOLUMNHEADER,  CRect(CPoint(0, 0),CSize(1600, 600)), this, 123444)) return -1;   if (!m_FindWindow->SetWindowPos(&wndTop, 0, 0, 1600, 600, SWP_DRAWFRAME | SWP_SHOWWINDOW)) return -1; }   ...   And this is the code that is called every time I push Ctrl + F   void Whatever::OnFindCommand(void) { m_FindWindow->ShowWindow(SW_SHOW); m_FindWindow->SetWindowPos(&wndTop, 0, 0, 1600, 600, SWP_DRAWFRAME | SWP_SHOWWINDOW); }     I don't know what is wrong but nothing appears on the screen...   Could you help me guys?
  13. help 3D space problem

    If c is the intersection point, you know that distance(b,c) =1, the angle between vector(b,c) and vector(a,c) is 90, and the distance(a,c) is known, so you can apply the pythagorean theorem.   distance(a,b)^2 = distance(b,c) ^2 + distance(c,a)   You can easyly get the distance(a,c)   Then it seems to be a Circle-circle intersection problem (Circle 1: center in a, radius is distance a,c and Circle 2: center is b distance 1)
  14.     If I am not wrong...WS_EX_TOPMOST is an extended style, the extended styles shoud be in the first parameter and the "normal" styles in the fourth   So it should be CreateWindowEx(WS_EX_TOPMOST,  "WindowClass", "Our Direct3D Program", WS_POPUP,...   Probably the WS_EX_TOPMOST is being interpreted wrong and there is a conflict with the WS_POPUP