Jump to content
  • Advertisement
    1. Past hour
    2. h8CplusplusGuru

      Tag-Team Challenge

      I'm down
    3. Dev Mandarkk

      Introduction

      About the project: Lockdown is a first person narrative walking simulator set on a space station orbiting an unknown planet with the aim of terraforming. You are a maintenance engineer on the space station and find yourself waking up in the medical wing only to discover that the entire crew is gone and has seemingly left you behind. A little about me: This is a project of many "firsts" for me: First project where I challenge myself to work in Unreal Engine. First project where I challenge myself to actually write C++ and not code the game entirely in blueprints (Despite the lack of C++ resources). First slightly ambitious project where as my past projects have mostly been idle clicker/endless runner mobile games. First time working in a team for a longer period of time and actually committing to an idea and work on it (Programmer + Artist + Animator). First time starting a devlog about a project I am working on and staying true to it (YouTube as well as here)! The developer logs here will supplement the devlogs on my YouTube: TP3. If you see something you like or if you have any questions or suggestions please feel free to jump in at any time and let me know! I am absolutely excited! See ya!😀
    4. Today
    5. Alberth

      #include <math.h>

      Maybe you are now using a newer c++, which uses #include <cmath> ? (.h extension is obsolete, standard includes don't have it, and the C libs now have a "c" prefix). You may want to read cppreference.com for details of the newer c++ -es.
    6. Ok, more progress. I added one extra transparent pixel at the top and bottom of the grass tile. This solved the issue. looks like OpenGL was sampling the pixel from the top to bottom? if that makes any sense. I don't know if this is a good solution. Does anyone know why this happens? Any thoughts? [Edit] more updates. If I set my window client rendering area resolution to 1280, 720 (the window size is actually 1296, 759 with borders) everything is rendered perfectly. If I make the client rendering area to 1920, 1080 (the window size is actually 1936, 1119 with borders) everything looks messed up. ugh... this is frustrating... It's 12:32 am... it's late. I'm going to bed. I will continue this tomorrow. 1280, 720 image 1920, 1080 image
    7. ok, here is some progress. By moving the sprite 0.5f units down the issue is kind of fixed? but not really? notice how the top green pixel is now at the bottom. left sprite is the original sprite. Right sprite is the one the engine is rendering. I'm reading about pixel perfect rendering and how in OpenGL (0, 0) is the center of a pixel not the top left of the pixel. So I have to add 0.5 to something? I don't know for sure... I'm still researching this. Any thoughts are much appreciated.
    8. ERASERHEAD STUDIO

      13 RONIN - DevLog #10 - Pain & Death

      Hello friends, The last couple of weeks I've been busy drawing pain and death animations for my samurai hero. Once again it became painfully apparent how slow this process is for me. This made me decide to focus on key-frames and use as few in-betweens as possible. By using different duration on different frames and adding some easy in-betweens I still think I can achieve somewhat decent animations. What do you think? There will be four different pain animations and at least five different death animations with some variations between characters. If the character is standing or crouching and from what direction the attack is coming will control what animation to play. Pain These are the four pain animations: The character is hit in the head or chest. The character is hit from behind or maybe hit in the stomach (not yet decided). I'm not sure what I think of this animation. What do you think? Should I keep it, or maybe try to draw something else. The character is hit while crouching. The character is hit from behind while crouching. Death And here are the four death animations: The character is killed from a hit in the head or chest. The character is killed from behind or maybe with a hit in the stomach (not yet decided). The character is killed while crouching. The character is killed from behind while crouching. Animation process I've got a lot of questions from friends and colleagues asking me how the animations are done, so here is a quick walkthrough of the process. When drawing, you can use any drawing software of choice, but I really recommend using a software that is specially made for the purpose of making sprite animations. I use a tool called Pyxel Edit, it's really good and quite affordable, go check it out. 1. Sketch First I sketch out the key-frames of the animation. This I do rather fast and sloppy. My only goal here is to get the pose and feeling right. For the first frame I use an existing image, in this case, the first frame from the crouch animation. In that way I know the character will get the same proportions as in already existing animations. But in this example I've, for consistency sake, sketched the first image as well. 2. Fill Done sketching I draw the character in solid colors. I do this on a separate layer on top of the sketch and adjust the transparency level so I can see the sketch beneath. I repeatedly play the animation and make adjustments until satisfied. Everything doesn't have to be perfect at this stage, but the motion should be "realistic" and the mass of the character should be the same throughout the animation. In this phase I also start playing with different duration for individual frames. 3. Detail I copy the animation to yet another layer and start filling in the details. When this is done I see if I can improve the overall feel by adding some easy in-betweens. By "easy in-betweens" I mean a frame I can create by copying an existing image and only change a minor part e.g. the hair or a part of the clothing. Detailed animation before adding any "easy in-between". Same animation but with an added frame in the middle. The ponytail lands on the head and the sword sheaths move. This was an "easy in-between." Without it the animation would have looked a little strange, don't you think? I hope you have enjoyed this and got a better understanding of the animation process. Next dev log will be about blood, it'll be awesome! Happy coding! /jan.
    9. ERASERHEAD STUDIO

      13 RONIN - DevLog #9 - A new milestone

      DevLog #9 - Next milestone - Easter! Hello friends! Next milestone in the development of 13 Ronin will be another public developer build. It will feature: Get ready text Game over text Time limit and counter Time-based score Gameplay: Instant action on button press, no need to follow through Minimum attack distance, no damage when the opponent is too close More varied movement scheme for the computer player Moves and attacks: Crouching turn Crouching cut Damage and death: Crouching hurt animation, forward and backward Crouching death animation, forward and backward More frames in the current death animation Death animation, forward Pool of blood under dead body Blood particles Different blood splashes depending on hit Happy coding! /jan.
    10. DavinCreed

      Depths of Orpheus - After the Prototype

      The dungeon crawler challenge was fun, and I was happy with what I was able to get done in the time frame. There was a lot I designed for the game but cut back to a minimum viable product in order to get the project done in time. Now I want to go in and add all that stuff in, and make a few changes based on playing the prototype. Since submitting the game, I've gone in and added a few things already. The enemies now drop some damaged loot, most of the level generation bugs have been worked out, the items show their quality and damage level so the player can choose whether to pick it up or keep what they got, and I adjusted the amount of items and mobs that spawn on the level. I have a huge list of things to get done for the game, and I'm going to work through them one at a time. I'm also doing another project to develop my game dev skills so this won't be worked on as much as I did during the challenge. I'm not entirely happy with the health system and there are some bugs with that still around. So I'm going to go back into the design and change a good chunk of that. I don't think I've given the health system a fair shake yet and I really think it's a good idea. The UI needs a lot of work, but I'm going to wait until the game is more complete/designed before I start working on that. One thing I want, is to be able to play the game with just a controller and not have to use the mouse. I'm thinking about also dropping the mouse interactions as well, or at least only popping it up in certain conditions. I think the game has a lot of potential, so over the next little bit, I'll be finishing the game.
    11. Thank you for your likes. I glad that my instructions are useful for somebody. But I will continue even nobody likes my instructions.
    12. Lendrigan Games

      Alternative names for fantasy classes

      It sounds like you already have a working list for what you need. 95% of classes for fantasy games are fighter/mage/thief, and the only real extension to the list is Dungeons & Dragons classes. With a better view of what you want, I've pulled up some more names for you. Knight - Sure, the word isn't obscure, but it's rarely used as a class name Shaman Man-At-Arms - Going by historical definition, can be used for cavalry or "weapon flexibility" Sniper Mystic Druid - Yes, it exists in D&D, but history doesn't have a lot of names for spellcasters Necromancer Berserker
    13. hplus0603

      Multiplayer networking for modded open source game?

      Yes! This is why RTS-es generally default to "explored map / fog of war." Although even the fog of war can be pierced by an appropriate network sniffer. Not during competitive events, though 🙂 A bunch of other cheats become impossible, though, because any attempt to deviate from the rules locally will lead to instant de-sync.
    14. hi, first off all be warned this will be a long post. ( One man one word, one woman one wordbook ) I implemented a GPU driven SPH simulation based on the blog of a forum member turanszkij and his blog wicked engine blog fluid-simulation/ The code of my compute shaders is below. At first version a naive brute force method is emplemented so every partice searches the whole particle list for other particle beeing a potential neighbour that gives density imfluence. A fool proof code that shall show me how the things work. At the moment we have 5000 particles with 40 FPS which is fast enough for evaluation. - 1. Pass calculate densities by looping each particle through ALL particles - 2. Pass calculate forces by looping each particle through all but not the own particle - 3. Pass calculate a simple Eular numerical integration to get velocity an new position I also made a nice GUI which lets me change all simulation parameters on the fly without recompiling the shader, just passing all values by constantbuffers What makes me soo discouraging is, that i cant find a set of parameters that gives realistic results. In all variations with, smooth length h, viscosity, reference density the particles move so la la but the whole simulation remains too spiky. Meaning that the particles like "to jump" too much. When changing parameters the particles fall into each other meaning that e.g. 8 spheres take together the volume of 2 spheres. I also could nowhere find how to calculate the parameters e.g. reference pressure - smooth distance h = 0.2 or h = 0.1 is set to the same value as the radius of my particles / spheres. - tried to clamp the resulting velocity of each particle to a maximum value to minimize the danger of "blowing up" the simulation by to fastly moving particles. - reduced the delta_time to keep simulation stable ( but keep fixed delta_time during the simulation ) I don' t just ask as a lazy person. I have studied very much the meaning of the smoothing kernel functions about the viscosity and pressure forces and know that it is hard to balance the system. In principal i want the behaviour of e.g. NVIDIA flex fluid demos, where the particles come very fast to rest position, that means there are no more working density forces and the spheres just touch one another. In the NVIDIA flex demos the paricles behave more like perls which like to clumb to each other. In my simulation the spheres never get to rest, which from theory i can understand because every last movement of a paricle changes density of the surounding particles that lead to new movements. Maybe i need another simulation model or other kernel function, or i have a tremendous bug in my code. I would realy thankfull if any kind person with more insight than i could give me a understandable advice. Evelyn static const uint nThreads = 1000; static const float SPH_PI = 3.141592654; static const float3 Gravity = float3(0, -9.8f * 1, 0); // natural gravity constant /* static const float delta_time = 0.016f * 0.2; static const float h = 0.2; // smoothing radius static const float h2 = h * h ; // smoothing radius ^ 2 static const float h3 = h2 * h; // smoothing radius ^ 3 static const float h6 = h2 * h2 * h2; // smoothing radius ^ 6 static const float h9 = h3 * h3; // smoothing radius ^ 9 static const float h3x2 = 2 * h3 ; // 2 * h ^ 3 static const float poly6 = 315.0 / (64.0 * SPH_PI * h9); // precomputed Poly6 kernel constant term static const float spiky = -45 / (SPH_PI * h6); // precomputed Spiky kernel function constaant term static const float K = 250.0; // pressure constant static const float p0 = 1.0; // reference density static const float E = 0.018 ; // viscosity constant static const float mass = 25.0; // mass for all the same in this version static const float border_reflect = 0.1f; // factor how much reflected velocity at borders to wheight */ static const float border_x = 1; static const float border_y_low = 0; static const float border_y_high = 500; static const float border_z = 1; // only as info, not used struct RWByteBuffer_layout { float4 Position ; float4 Color ; }; // structure buffer definition struct position_color_struc { float4 Position : POSITION; float4 Color : NORMAL; }; struct particle_struc { float density ; float pressure ; float3 force ; float3 velocity ; }; cbuffer CB_shared : register(b0) { uint particle_count; float delta_time; float h; float h2; float h3; float h6; float h9; float h3x2; float poly6; float spiky; float K; float p0; float mass; float E; float border_reflect; float max_velocity; } RWStructuredBuffer<position_color_struc> in_data : register(u2); RWStructuredBuffer<particle_struc> particles : register(u3); [numthreads(nThreads, 1, 1)] void Particles_density_ComputeShader(uint3 id : SV_DispatchThreadID) { uint range = 1 + particle_count / nThreads; particle_struc particle; position_color_struc inputA; position_color_struc inputB; float3 diff; float r2 ; float W; for (uint i = id.x * range; i < (id.x + 1) * range; i++) { if (i >= particle_count) continue; // read position from memory inputA = in_data[i]; // read particle from memory particle = particles[i]; // reset particle density particle.density = 0; // loop ALL particles for (uint j = 0; j < particle_count; ++j) { inputB = in_data[j]; diff = inputA.Position.xyz - inputB.Position.xyz; r2 = dot(diff, diff); // distance squared if (r2 < h2) { //normall we would calculate //W = poly6 * pow(h2 - r2, 3); // poly6 smoothing kernel //particle.density += particle.mass * W; // because we have same mass for all particles we can do multiplication with poly6 and mass // after the inner lopp //W = pow(h2 - r2, 3); // poly6 smoothing kernel //particle.density += W; // so in short particle.density += pow(h2 - r2, 3); // poly6 smoothing kernel; } } particle.density = particle.density * poly6 * mass; // Can't be lower than reference density to avoid negative pressure! particle.density = max(p0, particle.density); // calculate particle pressure // could be calculated in the following pass but for easy debugging calculate here and store in particle memory particle.pressure = K * (particle.density - p0); // Store particle to memory particles[i] = particle ; } } [numthreads(nThreads, 1, 1)] void Particles_forces_ComputeShader(uint3 id : SV_DispatchThreadID) { uint range = 1 + particle_count / nThreads; particle_struc particleA; particle_struc particleB; position_color_struc inputA; position_color_struc inputB; for (uint i = id.x * range; i < (id.x + 1) * range; i++) { if (i >= particle_count) continue; // Compute acceleration: float3 f_pressure = 0; // pressure force float3 f_viscosity = 0; // viscosity force // read particle A and position A from memory particleA = particles[i]; inputA = in_data[i]; // loop all particles for (uint j = 0; j < particle_count; ++j) { // step over comparing the particle A with himself if ( i == j) continue; // read position B inputB = in_data[j]; // Vector between particles float3 diff = inputA.Position.xyz - inputB.Position.xyz; // calculated distance squared float r2 = dot(diff, diff); // check if distance smaller then smoothing radius ; NOTE if r > 0 ; then if r < sqrt(r2) => r2 < SPH_h2 is also true if (r2 < h2) { float r; float r3; float3 rNorm; float W1; // just to distinguish that we calculate two different W values float W2; // m_quotient = particleB.mass / particleA.mass; // all particles have same mass so m_quotient = 1 const float m_quotient = 1; // calculate distance between particles r = sqrt(r2); // calculate r ^ 3 r3 = r2 * r; // calculate normalized direction vector between the particles ( len = 1 ) rNorm = diff / r; // read particle B from memory particleB = particles[j]; // spiky smoth for pressurce force W1 = spiky * pow(h - r, 2); // calculate and add pressure force f_pressure += m_quotient * ((particleA.pressure + particleB.pressure) / (2 * particleA.density * particleB.density)) * W1 * rNorm; // laplacian smoothing for viscosity force W2 = -(r3 / h3x2) + (r2 / h2) + (h / (2 * r)) - 1; // calculate and add viscosity force f_viscosity += m_quotient * (1.0f / particleB.density) * (particleB.velocity - particleA.velocity) * W2 * rNorm; } } // add forces with SPH_E as viscosity constant of the fluid particleA.force += Gravity + (f_viscosity * E - f_pressure) / particleA.density; // Store particle A to memory: particles[i] = particleA; } } [numthreads(nThreads, 1, 1)] void Particles_positions_ComputeShader(uint3 id : SV_DispatchThreadID) { uint range = 1 + particle_count / nThreads; particle_struc particle; position_color_struc input; for (uint i = id.x * range; i < (id.x + 1) * range; i++) { if (i >= particle_count) continue; // read particle particle = particles[i]; // debug test //particle.force = Gravity; // calculate velocity //Phsyics: V = V0 + a * dt // with a = Force / mass when mass = 1 : V = V0 + F * t particle.velocity = particle.velocity + particle.force * delta_time; //debug test, clamping velocity to max_velocity float velocity_strength = length(particle.velocity); if (velocity_strength > max_velocity) { particle.velocity = particle.velocity * max_velocity / velocity_strength; } // read position input = in_data[i]; // calculate new position //Phsyics: S = S0 + V * dt input.Position.xyz = input.Position.xyz + particle.velocity * delta_time; // reset force of particle particle.force = 0; // check if ground is surpassed if (input.Position.y < border_y_low) { input.Position.y = border_y_low; particle.velocity.y = - border_reflect * particle.velocity.y; } // check upper border is surpassed if (input.Position.y > border_y_high) { input.Position.y = border_y_high; particle.velocity.y = - border_reflect * particle.velocity.y; } // check left / right border if(input.Position.x < - border_x) { input.Position.x = -border_x; particle.velocity.x = - border_reflect * particle.velocity.x; } else if (input.Position.x > border_x) { input.Position.x = border_x; particle.velocity.x = - border_reflect * particle.velocity.x; } // check front / back border if (input.Position.z < -border_z) { input.Position.z = -border_z; particle.velocity.z = - border_reflect * particle.velocity.z; } else if (input.Position.z > border_z) { input.Position.z = border_z; particle.velocity.z = -border_reflect * particle.velocity.z; } // store position in_data[i] = input; // Store particle particles[i] = particle; } }
    15. Apologies for the bad image. Both tiles have different zoom level which I messed up in paint. Then I saved the image in jpg format then png which created these artifacts. My apologies. Here is a better image and I will also include a screenshot of my window and original tile. The projection matrix uses the correct client area size as opposed to the window size.
    16. Doctor Binary

      Tag-Team Challenge

      I think it should be permitted but not required. Collaboration comes with it's own set of challenges, and not everyone will be able to do it.
    17. Well hello there! Welcome to this week's Weekly Update! First, let's get something out of the way right now... I've talked about some kind of demo by the end of February, and unfortunately, it won't be possible. There's still a bunch of critical optimizations to be done before a demo can be made. I know there might be some of you that really wanted to try this game at once, but I guess my estimations weren't as exact as I thought... However, I really want this demo to be launched as soon as possible. Right now I'm aiming by probable end of March if not later, but I'll probably am going to keep you updated on that. But anyway, let's get right to the updates! Aside from many optimizations and refactoring, there are two new features: one is a bit more aesthetic and the other is more gameplay-specific. VFX First, let's talk about visual effects. Beforehand, there weren't any VFX at all (some actions did, however, induce effects like blinking, but those doesn't really count). Visual effects have a great role in UX in general. People usually like it when a lot of feedback is given when taking an action. This way it encourages the player to interact with the game, making the latter more immersive as a result. In particular, hitting, parrying and guarding didn't really shown any type of feedback what-so-ever, giving the impression that those actions didn't really exist in the first place. So to fix this I've decided to add some fancy particle systems that create nice visual effects for each of these specific actions. Let's take a look, shall we? (Keep in mind that these effects are subject to change) Hit VFX This is a quite simple effect that is being played when an attack successfully lands on an enemy. Right now it's a simple burst effect with circle particles. Their red-ish tint is also reminiscent of blood, strength and courage which are all feelings related to attacks in general. Its size depends on the amount of damage given. Guard VFX This one is quite fancy. It's supposed to mimic an impact flair. Its blue tint is also to represent metals hitting each other, as well as reinforcing the guarding by invoking ideas of trust and efficiency. (these circle particles are placeholders as of right now) Parry VFX This one is one of my favourites. It's supposed to represent some kind of burst, like if two opposing forces collided and released a bunch of energy altogether. The spiral movement is also supposed to invoke a sense of choreography, reinforcing the idea that the move was calculated and planned from the beginning. Its yellow colour also indicates a sense of pride and joy, but in another way, it also can induce anxiety and/or depression on the receiving end. That's about it for VFX. I'm also constantly working on these to get them just right. But let's take a look at these in action: SuperParry.mp4 Fruit Trees Finally, I've also added Fruit trees. These special props act as a food source. They could be found in any room and can sometimes bare some fruits. The player can easily eat some of these fruits for a temporary stat boost. Each tree can have many fruits spawner. After a fruit was eaten, another one grows back onto the tree after a while. That is if those fruits spawners didn't reach their regrowth limit, though. This means that players have to be wise about their fruit play. Here's a list of all fruit trees currently implemented in the game Banana plant This is a standard banana plant. It usually spawns in tropical/rainforest levels and whatnot. As the name suggests it can have bananas on it. Lime Tree A more standard tree, this one is all about that lime stuff. It is slightly smaller than banana plants, and although it's supposed to be a tree some concession had to be made in order for the fruits to be reachable. That's it for plants for now... If you're interested in fruits and how they work I suggest you take a look at my previous blog entry. Minor Updates We're still doing those refactorings, optimizations and whatnot. I would say that this was by far the things that took most of the development time. Cut a lot of duplicated shader code into their own .cginc files. This means cleaner code and smaller shaders overall. Refactored the code to remove a lot of duplicated code Added hit positions to damage events. Really useful to place those new visual effects Fixed bugs with sounds and food items Changed how diners menu works. Now they also use food spawner Fixed grass strain particles so that they also have a velvet finish to them Next week While the demo isn't going to launch this month, I'm still trying to get things done for an eventual demo. It's a lot of work to look at all those bits of code and think of other more optimized ways to achieve the same goals. It takes time and sometimes doesn't yield anything at all... So this means more tinkering, balancing, adjustments, optimizations and refactors... Aside from that, it's the usual suspects.
    18. First thing I noticed is that the left image is taller than the right image. This probably means that there's an error in your projection matrix. Wild guess, but are you running in a window, and using the full dimensions of that window (as opposed to the client area of the window) to set up your projection matrix? The second thing I noticed is that neither half of the image is clean pixel art. The image itself appears to be a png, but I'm seeing what can only be described as jpeg artefacts in the image. Was it like that when you uploaded it? When you ran the screen capture? In the source image?
    19. Project Name: Condors Vs. Ocelots Team Size: 15ish Genre:Strategy RPG Engine: Unity Roles Available: Currently in need of 2 2D sprite artists, 2 2D concept artists, and then finally 2 programmers. If you feel as if you can offer the team something more that isn’t listed, we are always open to making an exception, just send your resume/portfolio to us! Project Length: Currently planning on release Q1 2020. Compensation: Rev-share Project Description: Condors and Ocelots have been at war for generations. Battles have left some settlements in ruins. Others teem with refugees. Even away from the fighting, towns and villages suffer from having their fighting-age citizens lured away or conscripted by one faction or the other. Banditry is also rife -- since the Condors and Ocelots focus on the front lines, and largely neglect the parts of their respective dominions which aren't militarily important or located near their bases. The mysterious faction, Goatverlords, comes in and antagonizes both claiming rule of the land. They must work together and against one another to win the ultimate struggle. Project Status: Pre-design is completely done and we are starting on development of our builds. Send emails to careers@titanomachystudios.com Our store page can be found here, https://play.google.com/store/apps/developer?id=Titanomachy+Studios Our website here, http://titanomachystudios.com/#/
    20. Hi everyone, When I render a sprite in my engine which is using OpenGL 4.5, the pixel art looks different from what it is supposed to. Here is an image of how the art should look like vs how it looks like in my engine. The image on left is how the grass tile should look like. The image on the right is how my engine renders it. You can see the difference on the edge of the tile. The line is not quite straight. I'm using an orthographic matrix and the image position is at the origin (0, 0) which in my engine is in the middle of the screen. Anyone know what is causing this and how to fix it? Cheers!
    21. Never heard of it before. Seems to be down since August 2015, so this doesn't really seem to be a new issue. In any case, I'd really recommend web.archive.org for things like this: https://web.archive.org/web/20150730114233/http://www.wotsit.org/ Also, the kaitai.io format gallery is neat: http://formats.kaitai.io/
    22. Just throwing an idea out there, as I currently don't have the time to participate in challenges, but what do you all think of members partnering up and co-operating together to participate in a challenge? Maybe a challenge that is for teams of two?
    23. RoKabium Games

      ScreenShotSaturday

      Keeping up with the twitter hashtag of screen shots on Saturday!
    24. Here was a topic about wotsit.org being down. https://www.gamedev.net/forums/topic/677585-wotsitorg/ It was a bad surprise for me when i saw the website down. I did some search and found a "mirror". If anybody needs it then its here: https://hwiegman.home.xs4all.nl/file-formats.html https://hwiegman.home.xs4all.nl/ Im not in any way affiliated with that website. Just wanted to give updated info about it.
    25. I am a composer with 3 years of experience and I mainly do orchestra music. Recently I have been collaborating with Septopus doing the game 'Slingbot Boarding'. If anyone who is interested to collaborate a project with me feel free to message me. The links below are my composition examples so feel free to check it out. Spotify: Soundcloud:
    26. Mikael Henriksson

      Eight Entry - February 23, 2019

      Hi! This is the eight entry of my development blog for my project 'Tracked Mind'. I was planning on releasing a new video to show you all what the game looks like right now, but I discovered a bug when the Player interacts with some items. So the video will have to wait until I have fixed the bug , I decided to upload a few new screenshots instead. One of the screenshots shows an early version of an abandoned house that I’m currently working on. In the next blog post I’m planning on uploading another screenshot of the house to show you the progress. Items affected by physics are now making noises when moved or hit by something, they all make different sounds depending on what material they are made of What's new?: - Water reacts to the Player and creates ripples. - Items that are affected by physics will now make sounds when moved or hit by something. Known issues: - A bug stops the Player from interacting with some items. Take care! /Mikael Henriksson
    27. jbadams

      Alternative names for fantasy classes

      If you're just trying to find a simple source of inspiration, you could also try searching the definitions and looking through the list of synonyms. For example, when I look up the definition of "mercenary" I get the following synonyms: or the definition of "barbarian" gives me these: Obviously not all relevant or useful, but there are some potentially useable names there.
    28. Unless it isn't normalized 😉 If you want something that truly cannot represent something that isn't a rotation, use a scaled axis (i.e., axis angle but you store the angle in the length of the vector) But I agree, if you are doing something a potentially unlimited number of times, definitely think about how to actually solve the issue. For example in things like interactions, try reformulating your operation from a bunch of tiny deltas to "how to go from my initial state to the current state using just the initial and current inputs". Of course, in the case of a transform tree, things are limited by you tree depth, and if you need higher precision, use higher precision.
    29. Specifications: "Add(a, b)" method must to sum positive numbers. Specification name: Add_SumPositiveNumbers_ReturnsSum "Sub(a, b)" method must to subtract positive numbers. Specification name: Sub_SubtractPositiveNumbers_ReturnsSub Source Code: https://github.com/8Observer8/calculator-jasmine-es5 Instruction: Create the "calculator-jasmine-es5" folder Search in the Internet: cdn jasmine Create the "SpecRunner.html file in the "calculator-jasmine-es5" folder and add links on files: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Jasmine Spec Runner v3.3.0</title> <link rel="shortcut icon" type="image/png" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine_favicon.png"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine-html.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/boot.min.js"></script> <!-- include source files here... --> <script src="src_client/calculator.js"></script> <!-- include spec files here... --> <script src="src_specs/calculator_tests.js"></script> </head> </html> Note. Files "calculator_tests.js" was not created yet but we added links on them above. Create the "src_client" folder. Create the "calculator.js" file the the "src_client" folder Create the "src_specs" folder. Create the "calculator_tests.js" file the the "src_specs" folder Add our specs described above to the "calculator_tests.js" file: calculator_tests.js describe("Calculator", function() { it("Add_SumPositiveNumbers_ReturnsSum", function() { // Arrange var calculator = new Calculator(); var a = 5; var b = 2; var expectedSum = 7; // Act var actualSum = calculator.Add(a, b); // Assert expect(actualSum).toEqual(expectedSum); }); it("Sub_SubtractPositiveNumbers_ReturnsSub", function() { // Arrange var calculator = new Calculator(); var a = 5; var b = 2; var expectedSub = 3; // Act var actualSub = calculator.Sub(a, b); // Assert expect(actualSub).toEqual(expectedSub); }); }); Open the "SpecRunner.html" in a browser to run tests. You will see errors in the browser because we did not implement the methods: Add(a, b) and Sub(a, b) Let's implement these methods and open the "SpecRunner.html" in the browser again to run tests. You will see that the tests are passed. calculator.js var Calculator = function() { }; Calculator.prototype.Add = function(a, b) { return a + b; }; Calculator.prototype.Sub = function(a, b) { return a - b; };
    30. fatboxsoftware

      Free art assets

      I figured other developers out there might find some of this useful so I wanted to share it with the community. As noted in the header, this thread is open to user suggestions on free content, and I've put quite a few items up for download on a site I manage. They are open source with no strings attached. http://fatboxsoftware.com/resources.html
    31. Simplest example: you create a Listener in a different thread and get a race on your listener list. I would probably separate Listeners and "Listenables". Listeners could be constructed by passing in a reference to a Listenable (which is internally stored as a pointer). Automatically registering/unregistering could still be done in the constructor/destructor in that case. Or go for a "message bus" setup, as described in the wikipedia link All8Up posted. Casting a dervied pointer to a base pointer will get you the same result as evaluating the this pointer within the base class by definition. push_back default constructs an entry and then sets the value to what you pass in. emplace_back constructs your new value in place. For a pointer or plain int/float, it doesn't really matter, but there's no reason not to do it and as it does matter for more complex objects (and for non-default constructible objects it doesn't even work otherwise) so it's just a good habit.
    32. ePitts

      #include <math.h>

      Hi I've copied over to the new computer the vs files but unfortunately without dependencies. So while downloading those I get Errors like #include <math.h> could not be opened. Why and how to fix in my c++ vs community Project? Thanks
    33. MattGibson

      Showreel Feedback

      Hello there, I'm new here so hopefully I'm posting this in the right place! My name's Matt and I'm a composer, currently studying my final year of a BA (Hons) degree in Creative Music Technology, who's ultimately wanting to break into the video game industry. One of the assignments for the course requires me to contact industry professionals to try and obtain feedback on things like my web presence, showreel etc., and then create an action plan based on that feedback to try and improve my employability. I was just wondering if this would be the appropriate place to try and get some feedback from some fellow composers? And also, would anyone have any tips on reaching "potential clients" as it were, essentially audio directors etc.? I realise that games companies are likely to be inundated with cold emails from composers, so any pointers on how to establish some contact courteously would be appreciated. Thank you, and it's good to meet you all!
    34. a light breeze

      float or double for my vertices / normals?

      When considering the use of double precision floating point, the important question to ask is this: does this solve the precision problem or does it merely hide it? For example, if you have a rotation matrix and you keep multiplying it with other rotation matrices, then it will gradually cease to be a good approximation of a rotation matrix. If you use double precision instead of single precision, the same thing will happen, just at a slower rate. You're not solving the problem, you're just delaying when it becomes visible. On the other hand, if you regularly renormalise your rotation matrices, then your rotation matrices will stay as nearly perfect rotation matrices, even if you stick to single precision. Same thing if you use quaternions instead of matrices: a quaternion may contain a slightly incorrect rotation, but it will never represent something that isn't a rotation. There are cases where using double precision is an appropriate solution to a floating point precision problem, but it should not be the first tool you reach for in your toolbox.
    35. Nypyren

      Mathematically ideal field of view

      The mathematically ideal answer is: I CAN SEE EVERYTHING!!! But more seriously: I get motion sickness from narrow FOV. I have to intentionally use a field of view angle which looks unrealistic so that my brain doesn't try to pretend that it's reality. Games which don't allow for adjustable FOV infuriate me.
    36. FordPerfect

      Mathematically ideal field of view

      And then there's also virtual reality, where straying from "physical" FOV might be a Bad Idea.
    37. wintertime

      Multiplayer networking for modded open source game?

      Another problem would be map hacks and similar. If all hidden information is on the client, it can be revealed much easier.
    38. Well to be honest I haven't really thought of threading anything at this point, but yes, that is fair point. The thing I'm skeptical of this as well, that's why I asked, but it just seems such a straightforward way of doing the job that it's really tempting to use, are there any alternatives that don't rely on global state that would also work?
    39. What if you actually want two groups of listeners that get called in different contexts? How are you going to handle the case where you're constructing and calling listeners on multiple threads (eg. we enter vector's push_back on both threads at the same time)? What happens if a listener is in the middle of doing something unrelated on another thread when _Listener_UpdateAll is called? Is Listener responsible for unregistering itself, and if so, how are you going to ensure that classes implementing its interface actually do that? This isn't the worst possible use of global state, but I'm with All8Up in that we should generally be skeptical of global state. I would also say that having to call Update manually is a feature not a bug. In general you will find it easier to read, understand, and debug code where the control flow and data dependencies are explicit.
    40. Can you give an example of a possible way an error could effect the global state with the code I have shown? I'm just not picturing it. Also how can I eliminate the coupling altogether (and increase cohesion) of the model I've provided? Thanks, that's actually a much better way to do this. I've changed my code to reflect this. The reason I was doing it this way was because I thought that I needed to save the derived class's pointer (by casting it to a base pointer first) to make the correct virtual call. But I tried it and this works too (and now I don't have to manually invoke the base constructor on every derive, which is great). Can you explain why this works though? Also can you tell me why you're using emplace_back instead of push_back, from what I looked up its functionality is identical.
    41. khawk

      Gamedev api?

      On that particular item - latest topics on the front page - if you select the blue drop down that defaults to "Activity" and select "Forums", you'll see the latest topics. Same as going to the Forums tab on desktop. I know it's an extra step, but it will get the view you want for new posts/forum activity. The "reboot" I referenced is a complete review of these types of things. I'm hoping to have more to share on this in the coming months, depending on progress.
    42. VanillaSnake21

      Gamedev api?

      You mean particular functionality? Nothing out of the ordinary, something akin to reddit's api. Allow posting on user's behalf, allow deep queries, profile management. All the basics, but of course, the more functionality the better.
    43. CrazyCdn

      Gamedev api?

      @khawk Going to back only having the latest post on a topic on the main page, none of this 10 repeats on the same thread would be fantastic! Makes scrolling through to see new posts horrible on my phone. Honestly I flat out refuse to look at the site on my phone anymore unless it's to view replies to threads or PMs. Otherwise I will only view the site on my desktop.
    44. No way! I'm a fan, I actually own AO Tennis. If they're willing to answer fan mail from a hobbyist developer, I'm wondering if I could ask them a bit about their engine and animation system. But this might also be a conflict of their interests.. My burning question is will they make a sequel or continue building on the existing game? I'm guessing it's the former. Here's my WIP so far -- made 5 animations in a diamond shape (1 on each point + 1 center), and drew a circular hitbox since the racket face is large enough to round out the diamond's edges. Anything outside of that hitbox will require a different hitting anim, while anything within this hitbox counts as a safe clean hit and would look right. However this only works for the X/Y axis for balls where the player is stationary. For X/Z, I'm planning lots of different footwork patterns to account for z distance to the ball like approach shots and retreating shots. So far, so good! Really fun implementing the ideas we discussed.
    45. In this instruction we will study how to write executable specifications for a very simple Calculator project using Jasmine testing framework. Source code on GitHub: https://github.com/8Observer8/calculator-browserify-ts If you do not have "browserify" then install it globally using this command: npm install browserify -g Note. You can read about why we need "browserify" in this project in my instruction here: Browserify TypeScript Create the folder "calculator-browserify-ts" and install the necessary package: npm init -y npm i -D @types/jasmine Search in the Internet: jasmine cdn. Create the "SpecRunner.html" file and copy founded CDN links to it: SpecRunner.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Jasmine Spec Runner v3.3.0</title> <link rel="shortcut icon" type="image/png" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.0.0/jasmine_favicon.png"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.css"> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/jasmine-html.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.3.0/boot.min.js"></script> <!-- include source files here... --> <script src="dist_client/bundle.js"></script> <!-- include spec files here... --> <script src="dist_specs/bundle.js"></script> </head> </html> Let's describe specifications for our calculator. The calculator will have four operations: Add(a, b) Sub(a, b) Mul(a, b) Div(a, b) If "b == 0" then method "Div" will throw an exception with the text: "Divided by zero". Create the "src_specs" folder. Create the "calculator_tests.ts" in the "src_specs" folder Create the "src_client" folder. Create the "calculator.ts" in the "src_client" folder Let's create the first specification in the "calculator_tests.ts": import { Calculator } from "../src_client/calculator"; describe("Calculator", () => { it("Add_PositiveNumbers_ReturnsSum", () => { // Arrange let a = 9; let b = 1; let expectedSum = 10; // Act let actualSum = Calculator.Add(a, b); // Assert expect(actualSum).toBe(expectedSum); }); }); We could try to compile it but we cannot because we do not have the "Calculator" class. Let's add it in the "src_client" folder: calculator.ts export class Calculator { public static Add(a: number, b: number): number { return a + b; } } Add the "tsconfig.specs.json" file in the root of your projects: "tsconfig.specs.json" { "compilerOptions": { "sourceMap": true, "outDir": "dist_specs" }, "include": [ "src_specs/calculator_tests.ts", "src_client/calculator.ts" ], "exclude": [ "node_modules", "src_client" ] } Now we can compile and browserify the specification. Enter two commands: tsc -p tsconfig.specs.json browserify dist_specs/src_client/calculator.js dist_specs/src_specs/calculator_tests.js -o dist_specs/bundle.js You can add these commands to the "package.json" file in the "scripts" section: "scripts": { "build_specs": "tsc -p tsconfig.specs.json", "bundle_specs": "browserify dist_specs/src_client/calculator.js dist_specs/src_specs/calculator_tests.js -o dist_specs/bundle.js", "test": "echo \"Error: no test specified\" && exit 1" And you can run these short commands: npm run build_specs npm run bundle_specs Open the "SpecRunner.html" in the browser and you will see that the specification will run. Try to add another specifications for: Sub, Mul, and Div methods. Later I will add specification for "Divide by zero" exception.
    46. It is the most common problem for anyone who starts to study TS. They cannot include a few ".js" files after compilation to <script> tags in "index.html". It is very simple in JS. You have two files in JS and you can include them in "index.html": index.html <html> <head> <script src="js/sayHello.js"></script> <script src="js/main.js"></script> </head> </html> sayHello.js function sayHello(name) { console.log("Hello, " + name); } main.js function main() { sayHello("Ivan"); } window.onload = main; Output: But if you rewrite these files in TypeScript: sayHello.ts export function sayHello(name: string): void { console.log("Hello, " + name); } main.ts import { sayHello } from './sayHello'; function main(): void { sayHello("Ivan"); } window.onload = main; And if you compile them to JavaScript: tsc ts/main.ts ts/sayHello.ts --outDir "dist" You cannot just include this files in "index.html": <html> <head> <script src="dist/sayHello.js"></script> <script src="dist/main.js"></script> </head> </html> You will see this errors in the browser debug console: There are a few ways to solve this problem: You can concatenate all generated ".js" files in one bundle.js file using: Webpack, Gulp, Grund and so on. For example, see this official instruction: Gulp - TypeScript You can compile to AMD modules and use RequreJS to load them. For example, see my instruction: A few TypeScript files on Sandbox You can use Browserify to concatenate all generated ".js" files in one bundle.js file I will show you how to use Browserify. Install Browserify using this command: npm install browserify -g You can create bundle.js using this command: browserify dist/main.js dist/sayHello.js -o dist/bundle.js You will see "bundle.js" in the "dist" folder. Now you can include "bundle.js" in "index.html" using <script> tag: <html> <head> <script src="dist/bundle.js"></script> </head> </html> Open "index.html" file in a browser and you will see "Hello, Ivan" in the browser debug console. Bonus. UglifyJS You can install uglifyjs: npm install uglify-js -g And compress your "bundle.js" to "bundle.min.js": uglifyjs dist/bundle.js -o dist/bundle.min.js Do not forget to change a script name from "bundle.js" to "bundle.min.js" in "index.html": index.html <html> <head> <script src="dist/bundle.min.js"></script> </head> </html>
    47. khawk

      Gamedev api?

      Yes, there are plans for this that are part of a broader reboot. An official mobile app has also been looked at, but temporarily shelved for other priorities. Along those lines, if GameDev.net offered APIs, what would be of interest?
    48. There is a few TypeScript files in our example. We want to place these scripts on Sandbox. This is the result on the Sandbox: click. Open the debug console in your browser to see the result: "Ctrl+Shift+J" in Chrome. You will see in the debug console this messages: Create these files on Sandbox: https://plnkr.co/edit/ Program.ts import { Rectangle } from "./Rectangle"; export class Program { public static Main(): void { // Create a rectangle let rectangle = new Rectangle(); // Draw the rectangle rectangle.Draw(); } } Program.Main(); Rectangle.ts export class Rectangle { public x: number; public y: number; public constructor(x: number = 0, y: number = 0) { /* ... */ console.log("Rectangle was created"); } public Draw(): void { /* ... */ console.log("Rectangle was drawn"); } } We need to compile these files to AMD. For this, create the "tsconfig.json" file on the Sandbox: tsconfig.json { "compilerOptions": { "module": "amd", "outDir": ".", "sourceMap": true }, "include": [ "*.ts" ], "exclude": [ "" ] } Create the RequereConfig.ts file on the Sandbox: RequireConfig.ts requirejs.config({ baseUrl: "." }); requirejs(["Program"], (Program) => { }); Add "require.min.js" in the "index.html" file: index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>A few TypeScript files on sandbox</title> <script data-main="RequireConfig" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js"></script> </head> <body> <h3>See the console output. Press "Ctrl+Shiprt+J" in the Chrome browser.</h3> </body> </html> This is the result on the Sandbox: click. Open the debug console in your browser to see the result: "Ctrl+Shift+J" in Chrome. You will see in the debug console this messages: P.S. If you need to work locally you need to run these commands: npm init -y npm i -D @types/requirejs P.S.S. Read this book to learn more about AMD and RequireJS: Mastering TypeScript - 2nd Edition - Nathan Rozentals
    49. Yesterday
    50. Daniel Ricci

      Win Animation

      In my last post, I presented the Autocomplete feature that I implemented. This feature lets you right-click anywhere on the board, and all face-up top-most cards will attempt to put themselves in one of the four Foundation piles above the board. I also mentioned a handful of bug fixes that were done. This next and final feature that I will demonstrate here is the `Win Animation` feature that occurs when you win the game or push the Alt+Shift+2 key combination. The `Win Animation` is an animation that is played when you win the game. That is when all the cards are properly situated on each of the four Foundation piles above the board. The animation starts at the left-most pile, ending at the rightmost pile for each group of cards (Kings first, then Queen, Jack, 10, etc). The path that the card follows is similar to a sine/cosine wave. Each card has a wave randomly generated that fits within a specified period. These choices are limited to a set number of choices based on my observations of the original game, and there are quite a few randomly generated choices that can occur. I originally started prototyping this functionality using vanilla trigonometry, however, I found an implementation online that I felt was much simpler to implement, and that had much better readability for those not so fluent in the way of mathematical formulas. The implementation that I retrofitted into my game is the one from `Mr. Doob`, you can find the link to his code here. This is what the win animation looks like in my game (The animation is slow because of the recording software that I use, it is about twice as fast as this in RL) There are a few parts to the code to make this work, and I will explain the major players of this process in snippets below. For me to implement this animation I first created a class called `WinAnimationHelper` to manage the animation process. This class has a static method called `processCards` that gets called when someone wants to process all the cards on the Foundation piles (called when the game winning condition has been met). /** * Process all the cards held by the foundation views */ public static void processCards() { // Get the list of foundation piles List<FoundationPileView> foundationsList = AbstractFactory.getFactory(ViewFactory.class).getAll(FoundationPileView.class); // Reverse the list so that we start with the left-most pile. Collections.reverse(foundationsList); // Initialize this helper class initialize(); // Populate the queue of items to be processed _foundations.addAll(foundationsList); } Of interest is the `initialize()` method that I call above. This is a private static method that creates a timer that processes a field called _foundations at a rate of 80 times per second. After I perform a call to add the available foundations to the queue this timer will start to process them in a first come first serve fashion. For each foundation pile that it processes, it will grab the top-most card and create a WinAnimationHelper object, passing in the card that it received. Here is what the constructor of this class looks like. /** * The change in `x` over time */ private double _deltaX = Math.floor(Math.random() * 6 - 3) * 2; /* * The change in `y` over time */ private double _deltaY = -Math.random() * 16; /** * Constructs a new instance of this class type * * @param cardView The card view to animate */ private WinAnimationHelper(CardView cardView) { _cardView = cardView; Point position = cardView.getParentIView().getContainerClass().getLocation(); _x = position.getX(); _y = position.getY(); if(_deltaX == 0) { _deltaX = 1; } } The above code will first initialize the deltas for this card. For the rate of change on the X-Axis, the domain of available values are from [-6, 4]. For the rate of change on the Y-Axis, the range of available values are from (-16.0, 0]. I also handle an edge case where if the change in X is 0, I set it to 1 so that there is at least some movement along the X-Axis. After the object is constructed, my timer that created the object calls the method `update()` for each tick until the update can no longer occur because the card is out of bounds of the canvas dimensions. Here is what the method looks like. /** * Performs an update by performing both a next step point calculation and a draw routine * * @return TRUE if the operation was successful, false otherwise */ private boolean update() { Point point = calculateNextStep(); if(point == null) { return false; } draw(point); return true; } The above code is very straight forward, calculate the next location of the card, and then draw to that point. Here is the `calculateNextStep()` method. /** * Calculates the next position that the currently set card will be at * * @return The position associated with the next step where the card would be at */ private Point calculateNextStep() { // Take the change in X and the change in Y and apply them respectively _x += _deltaX; _y += _deltaY; // If you are outside the left or right canvas limits then the card should not // longer be positioned anywhere relevant so do not return any position if(_x < -CardView.CARD_WIDTH || _x > _canvasWidth) { return null; } // If the position is outside canvas height (with respect to the bottom of the card) if(_y > _canvasHeight - CardView.CARD_HEIGHT) { // Normalize the position of the card by placing it on the theoretical bottom of the canvas _y = _canvasHeight - CardView.CARD_HEIGHT; // Take the change in `y` inverse it, this along will cause the card to bounce upwards // Take only a small percentage of the delta so that it bounces less _deltaY = -_deltaY * 0.85; } _deltaY += 0.98; return new Point((int)_x, (int)_y); } The above code takes the currently computed deltas and adds them to the current x and y positions that were recorded by the card. If the `x` location is outside the bounds of the canvas then there is no more computation to be performed, this is our exit case. If this is not the case then I check to see if the `y` position is outside the lower bounds of the canvas. If it is, I position the card at the absolute bottom of the canvas and then I apply an inverse linear force to the current deltaY. This will cause the card to move upwards, however, only upwards by a certain percentage. This is an ever decreasing number that will simulate a `bounce` and that will eventually flatline itself with the y-axis if this statement is executed many times. Finally, I update the deltaY with a constant to ensure that the change in `y` counteracts the `bounce` effect. Once this is computed I perform a draw. Here is what the draw call looks like. /** * Draws the currently set card view to the specified position * * @param point The position to draw to */ private void draw(Point point) { CardView cardView = CardView.createLightWeightCard(_cardView); cardView.render(); ViewFactory viewFactory = AbstractFactory.getFactory(ViewFactory.class); GameView gameView = viewFactory.get(GameView.class); gameView.add(cardView, gameView.getComponentZOrder(viewFactory.get(StatusBarView.class))); cardView.setBounds(new Rectangle(point.x, point.y, _cardView.getWidth(), _cardView.getHeight())); } This was tough because I really wanted to just change the position of a single card and reuse the same draw buffer for performing the draw call just like in the original game. Doing this however was not possible because the layout manager that I am using is a Swing manager called GridBagLayout, and it was showing many artifacts that were making this functionality look horrible. So instead, for each point that I calculate I create a lightweight representation of the specified card view which is in layman terms a JPanel with an image. I take this card and I update it to the position that I calculated previously. I also make sure that it is added to the GameView and that it is positioned at the proper z-position. The finishing touches for this feature were to make sure that clicking anywhere during the animation or pressing on any key stops the animation and asks you if you want to play again, this is in line with the original game. So that is how I implemented the win animation. I also fixed a few more bugs, that I will outline below 1. performing an undo doesn't undo the score, it just subtracts 2 https://github.com/danielricci/solitaire/issues/164 2. Performing an automove no longer updates the score https://github.com/danielricci/solitaire/issues/155 3. Cannot perform an undo after doing an Autocomplete https://github.com/danielricci/solitaire/issues/153 The next thing on my list is to normalize the UI and I have a couple of bug fixes left to do. You can always follow my progress by following the game located at https://github.com/danielricci/solitaire, and if you have any questions I will do my best to answer them. Take care, until my next blog post.
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!