• 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.

Garra

Members
  • Content count

    112
  • Joined

  • Last visited

Community Reputation

103 Neutral

About Garra

  • Rank
    Member
  1. I'm working on a type of space shooter for android and needed some help with enemy AI. What I'm looking for is info on how to do things such as ship formations (making multiple ships follow a path) etc. I have worked with steering behaviors before, but I don't think it's quite what i'm looking for. I think the solution is more than likely pathing. I want ships to follow a bezier type path just like you see on nearly every space shooter. I also would like to be able to implement different types of ship formations. If someone could point me to some good resources or explain some of the logic to me I would be greatful. I've been looking around the net for a few days and haven't really found what I'm looking for.
  2. alright I'll give it a try, thanks for the advice.
  3. I'm trying to create a setup project for my game using the Visual Studio Installer, it all goes well until I install the game and click to run it. As soon as the game runs it comes up with the error R6010 - abort() has been called and gives me the abort/retry/ignore options. When clicking on retry the Just in time debugger pops up and opens up in visual studio.. i can actually use it to step over the run-time error and once past it the game runs completely normal. The game also runs from my compiler in debug mode without any issues. The game has many.. many lines of code so what would be a way to debug such an issue?
  4. EDIT: Issue solved I'm working on a TCP client/server and I'm having an issue with my connect function. The connect function is giving me the error code 10014, a description of the error code is below. I'm having some issues just figuring out what I need to do to fix it, any advice would be appreciated. [code][b]WSAEFAULT[/b]10014 Bad address. The system detected an invalid pointer address in attempting to use a pointer argument of a call. This error occurs if an application passes an invalid pointer value, or if the length of the buffer is too small. For instance, if the length of an argument, which is a [url="http://msdn.microsoft.com/en-us/library/windows/desktop/ms740496%28v=vs.85%29.aspx"][b]sockaddr[/b][/url] structure, is smaller than the sizeof(sockaddr). [/code] //my initialization code [code] bool CNetwork::InitializeTCPClient(char* szIP, int port) { iResult = WSAStartup(MAKEWORD(2,2), &wsaData); if (iResult != 0) return false; skSocket = socket(AF_INET, SOCK_STREAM, 0); if (skSocket == INVALID_SOCKET) return false; //Input server information ZeroMemory(&ServerAddress, sizeof(ServerAddress)); // clear the struct ServerAddress.sin_family = AF_INET; // set the address family ServerAddress.sin_addr.s_addr = inet_addr(szIP); // set the IP address ServerAddress.sin_port = htons(port); // set the port return true; } [/code] //connect function [code] bool CNetwork::Connect() { fd_set write; FD_ZERO(&write); FD_SET(skSocket, &write); FD_ISSET(skSocket, &write); TIMEVAL timeVal; timeVal.tv_sec = 0; timeVal.tv_usec = 1; if (select(0, NULL, &write, 0, &timeVal) == SOCKET_ERROR) { WSACleanup(); return false; } if (connect(skSocket, (struct sockaddr*)&ServerAddress, sizeof(sockaddr)) == SOCKET_ERROR) { int error = WSAGetLastError(); WSACleanup(); return false; } return true; } [/code]
  5. well i haven't actually tried limiting how much I send a packet to update the game, but technically it seems like as long as it updates fast enough then there would be no problem limiting the update to a certain number of frames. On a different note, I ended up having more issues with broadcasting a client's packet to other clients. When the client and server are on two different machines. The server receives the client's packet without issues and limited packet loss. However, when I try to make the server send that packet to all the other clients, the sendto() function is still returning SOCKET_ERROR and the server message "Unable to send to client" is being displayed. When both client and server are running on the same machine, the server seems to broadcast the packet to the other clients with limited packet loss. However, with the server receiving and broadcasting it is slowing it down greatly. I'm really confused about why the server isn't sending the received packets back out to the clients. My server's loop [code] while(true) { ZeroMemory(szBuffer, sizeof(szBuffer)); //iBytesRecv = c_Network.RecvChatPacket(szBuffer, sizeof(szBuffer)-1, 0); RecvPacket = c_Network.RecvPacket(RecvPacket); if (c_Network.Clients.size() > 0) { sprintf(szBuffer, "x: %f y: %f z: %f\n", RecvPacket.x, RecvPacket.y, RecvPacket.z); } //if the packet is a knock packet if (RecvPacket.knock) { c_Network.Clients.push_back(c_Network.IncomingAddress); } else //if it is a normal packet { //broadcast it to all the clients for (int i = 0; i < c_Network.Clients.size(); i++) { c_Network.SendPacketToClient(c_Network.Clients.at(i), RecvPacket); } } printf(szBuffer); } [/code] SendPacketToClient function [code] void CNetwork::SendPacketToClient(sockaddr_in client, Packet packet) { BYTE sendBuffer[128]; memcpy_s(&sendBuffer, 128, &packet, sizeof(packet)); int sent_bytes = 0; int attempts = 0; int packet_size = 0; while (sent_bytes < sizeof(packet) /*&& attempts < 3*/) { packet_size = sizeof(packet) - sent_bytes; int send_err = sendto(skSocket, (char*)&sendBuffer[sent_bytes], packet_size, 0, (sockaddr*)&client, sizeof(sockaddr)); if (send_err == SOCKET_ERROR) { printf("Unable to send to client\n"); } sent_bytes += send_err; } } [/code]
  6. another quick question, lets say I'm sending packets to update the player positions of a arena type fps. should I be sending the player position's to the server every single game frame?
  7. the issue is I'm trying to broadcast the packet received from the client with SendPacketToAll. However inside the SendPacketToAll function I'm calling sendto, which is always returning SOCKET_ERROR and therefore the packet is never broadcasted to the other clients. When I added in breakpoints, it seems like the IncomingAddress isn't being added to the ClientAddress array so I think the problem is here. Could you recommend a different way to handle the client addresses? [code] for (int i = 0; i < 8; i++) { if (!(c_Network.ClientAddress[i].sin_family)) { c_Network.ClientAddress[i] = c_Network.IncomingAddress; break; } } [/code] EDIT: I changed my ClientAddress Array to a vector and that seemed to solve most of my issues. It would probably be better to use a list though to make removing clients easier. [code]if (RecvPacket.knock) { c_Network.Clients.push_back(c_Network.IncomingAddress); } [/code]
  8. I'm working on a UDP server/client setup to add to my game. I have the client sending a structure of data representing a packet. This part is working, however I'm having issues trying to get the server to send the packet back out to all the other clients. Basically in my server loop I'm receiving packets, checking to see if the packet is a knock packet, and if it is add that address to a Client address array like below. [code] while(true) { ZeroMemory(szBuffer, sizeof(szBuffer)); //iBytesRecv = c_Network.RecvChatPacket(szBuffer, sizeof(szBuffer)-1, 0); RecvPacket = c_Network.RecvPacket(RecvPacket); sprintf(szBuffer, "x: %f y: %f z: %f\n", RecvPacket.x, RecvPacket.y, RecvPacket.z); //int packet_size = sizeof(RecvPacket); // //if (packet_size > 0) //{ //if the packet is a knock packet if (RecvPacket.knock) { for (int i = 0; i < 8; i++) { if (!(c_Network.ClientAddress[i].sin_family)) { c_Network.ClientAddress[i] = c_Network.IncomingAddress; break; } } continue; } printf(szBuffer); c_Network.SendPacketToAll(RecvPacket); } [/code]. My client is able to send packets to the server with the below function, so I tried to modify the function to work with my server in order to send the packet to broadcast the packet to the rest of the clients. [code] void CNetwork::SendPacket(Packet packet) { BYTE sendBuffer[128]; memcpy_s(&sendBuffer, 128, &packet, sizeof(packet)); int sent_bytes = 0; int attempts = 0; int packet_size = 0; while (sent_bytes < sizeof(packet) /*&& attempts < 3*/) { packet_size = sizeof(packet) - sent_bytes; int send_err = sendto(skSocket, (char*)&sendBuffer[sent_bytes], packet_size, 0, (sockaddr*)&ServerAddress, sizeof(sockaddr)); sent_bytes += send_err; } } [/code] This function is ment to send the packet from the server to all clients connected. However, the sendto function always returns -1. [code] void CNetwork::SendPacketToAll(Packet packet) { BYTE sendBuffer[128]; memcpy_s(&sendBuffer, 128, &packet, sizeof(packet)); int sent_bytes = 0; int attempts = 0; int packet_size = 0; for (int i = 0; i < 8; i++) { if (ClientAddress[i].sin_family) { while (sent_bytes < sizeof(packet)) { packet_size = sizeof(packet) - sent_bytes; int send_err = sendto(skSocket, (char*)&sendBuffer[sent_bytes], packet_size, 0, (sockaddr*)&ClientAddress[i], sizeof(sockaddr)); if (send_err == SOCKET_ERROR) { printf("Unable to send to client\n"); } sent_bytes += send_err; //attempts++; } } //Reset variables for use with next client address sent_bytes = 0; attempts = 0; packet_size = 0; } } [/code] and here is the server's receive packet function to show how IncomingAddress is being used. When the client starts up it will initialize winsock and then send the knock packet. When the server receives the knock packet it adds the IncomingAddress to the ClientAddress array. [code] Packet CNetwork::RecvPacket(Packet packet) { BYTE recvBuffer[128]; int recvd_bytes = 0; int packet_size = 0; int attempts = 0; int result; while (recvd_bytes < sizeof(packet)) { iAddressLength = sizeof(IncomingAddress); packet_size = sizeof(packet) - recvd_bytes; result = recvfrom(skSocket, (char*)&recvBuffer[recvd_bytes], packet_size, 0, (sockaddr*)&IncomingAddress, &iAddressLength); if (result == SOCKET_ERROR) { } recvd_bytes += result; } if (recvd_bytes == sizeof(packet)) { memcpy_s(&packet, sizeof(packet), &recvBuffer, sizeof(packet)); } return packet; } [/code]
  9. It's... very large. Why I didn't consider this being the problem sooner is beyond me. I was thinking of maybe calling it after so many frames instead of every frame.. or maybe redoing it completely. It basically does a line-triangle intersection test on triangles in the current node and then determines the height of the triangle. It's based from a tutorial on terrain quadtree's since I was learning them at the time. Edit: Not calling it every frame seems to improve the performance considerably. I found a decent frame number to keep the position transition smooth and have a much higher frame rate. I still may do some work on the GetHeightAtPosition function though. Also, thanks for the info on the profiling, this thread was worth it just to learn about those. Sure was easy narrowing the problem down with Very Sleepy ;o [code]bool CQuadTree::GetHeightAtPosition(float positionX, float positionZ, float& height) { float meshMinX, meshMaxX, meshMinZ, meshMaxZ; meshMinX = m_parentNode->positionX - (m_parentNode->width / 2.0f); meshMaxX = m_parentNode->positionX + (m_parentNode->width / 2.0f); meshMinZ = m_parentNode->positionZ - (m_parentNode->width / 2.0f); meshMaxZ = m_parentNode->positionZ + (m_parentNode->width / 2.0f); // Make sure the coordinates are actually over a polygon. if((positionX < meshMinX) || (positionX > meshMaxX) || (positionZ < meshMinZ) || (positionZ > meshMaxZ)) { return false; } // Find the node which contains the polygon for this position. FindNode(m_parentNode, positionX, positionZ, height); return true; }[/code] [code] void CQuadTree::FindNode(NodeType* node, float x, float z, float& height) { float xMin, xMax, zMin, zMax; int count, i, index; float vertex1[3], vertex2[3], vertex3[3]; bool foundHeight; // Calculate the dimensions of this node. xMin = node->positionX - (node->width / 2.0f); xMax = node->positionX + (node->width / 2.0f); zMin = node->positionZ - (node->width / 2.0f); zMax = node->positionZ + (node->width / 2.0f); // See if the x and z coordinate are in this node, if not then stop traversing this part of the tree. if((x < xMin) || (x > xMax) || (z < zMin) || (z > zMax)) { return; } // If the coordinates are in this node then check first to see if children nodes exist. count = 0; for(i=0; i<4; i++) { if(node->nodes[i] != 0) { count++; FindNode(node->nodes[i], x, z, height); } } // If there were children nodes then return since the polygon will be in one of the children. if(count > 0) { return; } // If there were no children then the polygon must be in this node. Check all the polygons in this node to find // the height of which one the polygon we are looking for. for(i=0; i<node->triangleCount; i++) { index = i * 3; vertex1[0] = node->vertexArray[index].x; vertex1[1] = node->vertexArray[index].y; vertex1[2] = node->vertexArray[index].z; index++; vertex2[0] = node->vertexArray[index].x; vertex2[1] = node->vertexArray[index].y; vertex2[2] = node->vertexArray[index].z; index++; vertex3[0] = node->vertexArray[index].x; vertex3[1] = node->vertexArray[index].y; vertex3[2] = node->vertexArray[index].z; // Check to see if this is the polygon we are looking for. foundHeight = CheckHeightOfTriangle(x, z, height, vertex1, vertex2, vertex3); // If this was the triangle then quit the function and the height will be returned to the calling function. if(foundHeight) { return; } } return; } [/code] [code] bool CQuadTree::CheckHeightOfTriangle(float x, float z, float& height, float v0[3], float v1[3], float v2[3]) { float startVector[3], directionVector[3], edge1[3], edge2[3], normal[3]; float Q[3], e1[3], e2[3], e3[3], edgeNormal[3], temp[3]; float magnitude, D, denominator, numerator, t, determinant; // Starting position of the ray that is being cast. startVector[0] = x; startVector[1] = 0.0f; startVector[2] = z; // The direction the ray is being cast. directionVector[0] = 0.0f; directionVector[1] = -1.0f; directionVector[2] = 0.0f; // Calculate the two edges from the three points given. edge1[0] = v1[0] - v0[0]; edge1[1] = v1[1] - v0[1]; edge1[2] = v1[2] - v0[2]; edge2[0] = v2[0] - v0[0]; edge2[1] = v2[1] - v0[1]; edge2[2] = v2[2] - v0[2]; // Calculate the normal of the triangle from the two edges. normal[0] = (edge1[1] * edge2[2]) - (edge1[2] * edge2[1]); normal[1] = (edge1[2] * edge2[0]) - (edge1[0] * edge2[2]); normal[2] = (edge1[0] * edge2[1]) - (edge1[1] * edge2[0]); magnitude = (float)sqrt((normal[0] * normal[0]) + (normal[1] * normal[1]) + (normal[2] * normal[2])); normal[0] = normal[0] / magnitude; normal[1] = normal[1] / magnitude; normal[2] = normal[2] / magnitude; // Find the distance from the origin to the plane. D = ((-normal[0] * v0[0]) + (-normal[1] * v0[1]) + (-normal[2] * v0[2])); // Get the denominator of the equation. denominator = ((normal[0] * directionVector[0]) + (normal[1] * directionVector[1]) + (normal[2] * directionVector[2])); // Make sure the result doesn't get too close to zero to prevent divide by zero. if(fabs(denominator) < 0.0001f) { return false; } // Get the numerator of the equation. numerator = -1.0f * (((normal[0] * startVector[0]) + (normal[1] * startVector[1]) + (normal[2] * startVector[2])) + D); // Calculate where we intersect the triangle. t = numerator / denominator; // Find the intersection vector. Q[0] = startVector[0] + (directionVector[0] * t); Q[1] = startVector[1] + (directionVector[1] * t); Q[2] = startVector[2] + (directionVector[2] * t); // Find the three edges of the triangle. e1[0] = v1[0] - v0[0]; e1[1] = v1[1] - v0[1]; e1[2] = v1[2] - v0[2]; e2[0] = v2[0] - v1[0]; e2[1] = v2[1] - v1[1]; e2[2] = v2[2] - v1[2]; e3[0] = v0[0] - v2[0]; e3[1] = v0[1] - v2[1]; e3[2] = v0[2] - v2[2]; // Calculate the normal for the first edge. edgeNormal[0] = (e1[1] * normal[2]) - (e1[2] * normal[1]); edgeNormal[1] = (e1[2] * normal[0]) - (e1[0] * normal[2]); edgeNormal[2] = (e1[0] * normal[1]) - (e1[1] * normal[0]); // Calculate the determinant to see if it is on the inside, outside, or directly on the edge. temp[0] = Q[0] - v0[0]; temp[1] = Q[1] - v0[1]; temp[2] = Q[2] - v0[2]; determinant = ((edgeNormal[0] * temp[0]) + (edgeNormal[1] * temp[1]) + (edgeNormal[2] * temp[2])); // Check if it is outside. if(determinant > 0.001f) { return false; } // Calculate the normal for the second edge. edgeNormal[0] = (e2[1] * normal[2]) - (e2[2] * normal[1]); edgeNormal[1] = (e2[2] * normal[0]) - (e2[0] * normal[2]); edgeNormal[2] = (e2[0] * normal[1]) - (e2[1] * normal[0]); // Calculate the determinant to see if it is on the inside, outside, or directly on the edge. temp[0] = Q[0] - v1[0]; temp[1] = Q[1] - v1[1]; temp[2] = Q[2] - v1[2]; determinant = ((edgeNormal[0] * temp[0]) + (edgeNormal[1] * temp[1]) + (edgeNormal[2] * temp[2])); // Check if it is outside. if(determinant > 0.001f) { return false; } // Calculate the normal for the third edge. edgeNormal[0] = (e3[1] * normal[2]) - (e3[2] * normal[1]); edgeNormal[1] = (e3[2] * normal[0]) - (e3[0] * normal[2]); edgeNormal[2] = (e3[0] * normal[1]) - (e3[1] * normal[0]); // Calculate the determinant to see if it is on the inside, outside, or directly on the edge. temp[0] = Q[0] - v2[0]; temp[1] = Q[1] - v2[1]; temp[2] = Q[2] - v2[2]; determinant = ((edgeNormal[0] * temp[0]) + (edgeNormal[1] * temp[1]) + (edgeNormal[2] * temp[2])); // Check if it is outside. if(determinant > 0.001f) { return false; } // Now we have our height. height = Q[1]; return true; } [/code]
  10. alright sooo i downloaded both of those. I was looking through the results Very Sleepy gave me and on enemy update function it was showing 12.96s in the inclusive column. I clicked there and it said CQuadTree::GetHeightAtPosition was 12.95s and the %calls was at 99.93%. I went into my game code and just completely commented it out and the FPS went back up to normal. However, That function of course is used to set the enemy y position to the height of the terrain where the enemy is at that time. [code] void CEnemy::Update(CQuadTree* terrain, D3DXVECTOR3 playerPos) { //y position on top of the terrain float height; //if the enemy is alive if (m_bAlive) { //Get the distance between the player and the enemy float dist = sqrt((playerPos.x - m_vPos.x)*(playerPos.x - m_vPos.x) + (playerPos.z - m_vPos.z)*(playerPos.z - m_vPos.z)); //If the distance is less than 20 if (dist <= 20.0f) { //Chase the player m_bEngaged = true; } //If not engaged if (!(m_bEngaged)) { //Chase randomly generated vector Search(); } else { //Chase player Chase(playerPos); } /*PROBLEM AREA*/ //Get the height of the terrain at the current enemy position and //set the enemies height to be slightly higher. //if (terrain->GetHeightAtPosition(m_vPos.x, m_vPos.z, height)) //{ // m_vPos.y = height + 2.5f; //} //Update the bounding sphere around the enemy m_sHitSphere.c = m_vPos; m_sHitSphere.r = 2.0f; } } [/code] Edit: It would appear my game just isn't a big fan of the GetHeightAtPosition function in my quadtree class. I use the same function for my camera/player to be able to walk on top of the terrain. When commenting out I notice a increase in FPS, not as drastic as what is happening with my enemies though. The code for this is pretty large and is taking to much time to be called every frame. I may try to only call every so many frames or something.
  11. umm could you explain a little on profiling, I did a little research and it looks like Visual Studio Ultimate and Premium have a in-built profiler, but I'm using Professional edition ;o. I think the profiling idea is the best option as well, even with using the sqrt function calculating distance it seems kinda extreme that spawning a single enemy jumps the FPS from 400+ to 60 and at times goes as low as 30. Edit: This is being done with DirectX10, not OpenGL. I currently have it set up so I press a keyboard key that tells that a new enemy should be made. I initialize that enemy. The init function creates the actual object which right now is just some vertices that make up a square. Then calls D3DX10CreateMesh to make a mesh with the vertex and index info and sets initial enemy position. Then I have a basic update function that controls the AI and tells it when to do the different AI tasks such as wandering and chasing. Then the render function just sets the enemies transforms and sends the mesh off to the color shader class for rendering. Editx2: It isn't the distance formula, I can comment out all of the AI movements and just have the box rendering and the FPS drops. Maybe it's because I'm creating new vertices and a new mesh for every enemy in the Initialize function?
  12. Thanks I managed to get that part working, however I would like some advice on optimization techniques to use, since after adding 2-3 enemies the FPS is dropping dramatically. There's a few things I'm currently doing to cause the issue, such as using the distance formula to calculate the distance between all the enemies and the player ever frame. All the enemies also draw no matter if they are in the view area or not. I'm still making optimizations such as adding bounding volumes and calculated collisions instead of distance. I thought about adding only frustum culling but that wouldn't solve the issue since my AI is designed zergling-like and you could have many enemies in your view at a time. I also thought about adding in some type of grid or tree, do you have any advice on what to add to solve my optimization issues?
  13. Thanks for explaining. The reason I mentioned moving the initialization code was because I'm calling the initialization function of the enemy class from my games Initialization function which of course gets called once. When I want to randomly add another enemy I would have to call that enemies initialize function, just not constantly like it would in the game loop.
  14. Whats the difference in adding a container inside of the class and just adding a container of enemy objects in say the main game file, for instance main.cpp. Maybe I'm misunderstanding, but it seems I would also have to due away with the initialization function of the enemy class.
  15. So I have a AI class that allows me to initialize a certain number of enemies and that's the number of enemies I have in the game. However, it doesn't allow me to do more interesting techniques with my AI such as spawning two new enemies when one enemy dies or just spawning an enemy on the fly. Basically I want to change the class to give me the ability to create new enemies at any time in the game. My current class has a initialization function that initialized the initial positions of the enemies, sets up the shader, and the enemy object itself. Most of this could be moved outside of the class, except there will be a problem with setting the enemies initial position. I thought of some other ways to do it without modifying my class since creating and destroying objects can be expensive. One of these ways is to make a pool of enemies. I could create a set number of enemies, put them in two vectors or something based on rather or not they are used and then swap the objects around. It seems like this wouldn't work in some cases since you would eventually run out of enemy objects. Does anyone have some advice to gvie me on a good method to set up creating new enemies at any time while the game is running?