Jump to content
  • Advertisement

BurdenJohn

Member
  • Content Count

    26
  • Joined

  • Last visited

Everything posted by BurdenJohn

  1. I wanted to know when it comes to using UDP in a game for real-time movement, if I should build an ack layer on top of it.   My game uses an 8-directional movement system. And right now I'm sending keypresses/keyreleases. It works completely fine with UDP, but I'm running it locally.   Eventually when players try sending data to my server via my external IP, there are most likely going to be datagrams dropped. So I was thinking of building an ack layer over top of it, which works like this:   My player would send a movement datagram, saying that he moved to the left. The server may/may not receive this. If it does receive this, the server will then send back an acknowledgement. If the client does not receive this after a certain amount of time (I set an alarm which is equal to double the ping), then we assume the datagram was dropped and we send the exact same data (move left) to the server and the process repeats until we have an acknowledgement.   The same system is implemented on the server in which the server would then send the move packet back to the client to allow it to move, and wait for an acknowledgement. If it doesn't get one, it re-transmits.   So now it comes to my two questions:   1) Is this a fairly efficient system for an acknowledgement system over-top of UDP messages that are required to be sent/received? When it comes to things like movement and actions in real-time in which dropped messages can have an effect on the game/   2) Is this system really necessary? In other words, do I really need to worry about datagrams being dropped?   I've heard that in reality, it really doesn't happen that often, but when you've got a ton of real-time movement data being transmitted back and forth, one would think it would happen.   The thing is, the way my movement system works is, the server is in control of the movement. The client simply sends a keypress/keyrelease and doesn't move the player until the server sends back a movement datagram. I mention this because, if a datagram gets dropped and I don't have any sort of re-transmit system in place, there would be times when the player would press the movement keys and not even move anywhere because a datagram got dropped.   This can be very annoying, and I know games such as Halo use this system (waiting for the server to tell us to move rather than the clients moving on their own). And games like that, you hardly ever have times where you would press the movement keys and nothing would happen. Most likely because they have some sort of UDP-ack-reliable system implemented overtop of UDP.   So is it worth it to implement an ack system for things like UDP movement? Or should I not even worry about it? I'm not exactly sure on average, how often a datagram is dropped, and if it would heavily interfere with gameplay?
  2. So basically I have a design for attempting to do multiplayer matchmaking.   Essentially what it is, is the ability for people to host their own games, without the need of: - Dedicated hosting (the server) - Port forwarding (TCP and UDP)   First off, do you think matchmaking is better or worse for people who wish to play your multiplayer game? By that I mean, will it drive people away or closer to playing your game? Will your game be more popular if you offer matchmaking or more popular if you allow people to host their own servers?   Anyways, my design for matchmaking is that everyone connects to one server of which I host (or have dedicated hosting somewhere else, none the less same thing).   When a player wishes to "host" a game, a message is sent to the server and the server will create an instance of a class known as "Match".   Match will hold all the information necessary for a game match, - Instances of incoming players (player names, keypress/keyreleases, positions, score, etc.) - Who the host is - The scores of the players - What's currently happening in the game - Solid blocks   With that said, Match will be doing a lot of work. For example, in this game, there are multiple rooms to the world. Each room has its own list of solid blocks for the server to do collision checks. The reason for this is, it needs the information about the map, because the client also has this information.   The clients are basically a dummy. The only thing they do is send keypress/keyreleases, and the server will update the position of the players, and check collisions. The server then sends keypress/keyreleases back to everyone (including the player), as well as the new positions of the player, and the clients will update the position/move the player/stop moving the player accordingly. This way, the clients have no way of modifying their position for their advantage.   Anyways, like I said the Match class does a lot of work. Because the server checks for collisions on its side as well, the server must contain: - A list of all the rooms - For each room, a list of solid blocks and their positions   With that said, there would be multiple Match instances. Depending on how popular the game is, there could be as few as 10 or even 30 to 40 Match instances.   That's 10-40 threads, or maybe 2 threads for each Match. One thread would be for game logic (updating player positions, collisions), and the other thread would be for networking logic (what to do for incoming messages).   All of that plus the main server thread that listens for incoming messages (TCP and UDP).   Is this efficient for a small server computer to do? Or would it just be better to let players host their own servers?   What do you guys think? Am I overcomplicating it?
  3. THIS CODE ON THIS POST IS NOW OBSOLETE. Please refer to this post (current method for movement collisions in a topdown environment): http://www.gamedev.net/topic/657046-topdown-wall-collision-not-working/?view=findpost&p=5156335   Still having trouble, player gets stuck along the bottom of the blocks while moving to the left and pushing up (player stops moving to the left for some reason).   Using SFML simply for drawing, gameplay is implemented using basic logic   I'm currently trying to do smooth top-down collision in which I use intersecting rectangles to detect if my player is going to be colliding with a rectangle given his velocity in x- and y-directions.   Here's my rectangle struct:   arectangle.h struct RECTANGLE{ int left, top, right, bottom; }; My block class: #include <SFML/Graphics.hpp> #pragma once class Block{ sf::RenderWindow* window; public: Block(sf::RenderWindow* _wind, int _x, int _y, int _size); sf::RectangleShape mask; void draw(); int x, y; int size; }; The main importance in the block class is x, y, and size (32 in my test case). Here's my block instances, as well as my player which gets a reference to the blocks vector: (main.cpp) vector<Block> blocks; Block b1(&window, 96, 32, 32); Block b2(&window, 32, 160, 32); Block b3(&window, 0, 0, 32); blocks.push_back(b1); blocks.push_back(b2); blocks.push_back(b3); SFMLPlayer player(&window, &blocks); The player is situated at position 32, 32 (with size rectangle 32).   And now here's the collision code, in SFMLPlayer.cpp: bool SFMLPlayer::IntersectRect(RECTANGLE* r1, RECTANGLE* r2) { return ! ( r2->left > r1->right || r2->right < r1->left || r2->top > r1->bottom || r2->bottom < r1->top ); } //Gets run at 60fps void SFMLPlayer::update(){ int room_width = 200; //temp int room_height = 200; //temp int hmove, vmove; hmove = (right - left); vmove = (down - up); int move_speed = 2; bool place_meeting = false; for(std::vector<Block>::iterator block = blocks->begin(); block != blocks->end(); ++block) { RECTANGLE prect; prect.left = this->x + hmove; prect.top = this->y + vmove; prect.right = prect.left + this->size; prect.bottom = prect.bottom + this->size; RECTANGLE brect; brect.left = block->x; brect.top = block->y; brect.right = block->x + block->size; brect.bottom = block->y + block->size; if(IntersectRect(&prect, &brect)){ place_meeting = true; break; } } x += ( hmove * move_speed ) * !place_meeting; y += ( vmove * move_speed ) * !place_meeting; //room boundaries check if(x + size + hmove > room_width+1){ x = room_width - size + 2; } if(x - hmove < 0-1){ x = -2; } if(y + size + vmove > room_height+1){ y = room_height - size + 2; } if(y - vmove < 0-1){ y = -2; } mask.setPosition(x, y); } I'm using a boolean: place_meeting() to detect if my (player + velocity) rectangle is going to hit any of the blocks using my InterSectRect(RECT*, RECT*) function.   And if it is, I set place_meeting to true and break out of the loop.   There are a few problems which I will display in an image: I can't even get to the left side of the room, I'm blocked out by that block in the bottom left. Its like its entire left side is expanded to the other parts of the room (as shown in the green marker line in the second picture).   After some more testing I found out that I can't get past the top part of any blocks. I can get past the bottom parts though.   Here's three more pictures:
  4. BurdenJohn

    Topdown wall collision, not working

    Got it working! //Simple rectangle intersection function bool intersect(RECTANGLE a, RECTANGLE b) { if (a.left < b.right && b.left < a.right && a.top < b.bottom) return b.top < a.bottom; else return false; } //Loops through all solids to see if two rectangles (given offset) //are intersecting. bool Player::place_meeting(int offsetx, int offsety, RECTANGLE prect){ RECTANGLE pNew; pNew = prect; pNew.left+=offsetx; pNew.right+=offsetx; pNew.top+=offsety; pNew.bottom+=offsety; bool inter = false; for(std::vector<Block>::iterator block = blocks->begin(); block != blocks->end(); ++block) { RECTANGLE brect; brect.left = block->x; brect.top = block->y; brect.right = block->x + block->size; brect.bottom = block->y + block->size; inter = intersect(pNew, brect); if(inter) break; } return inter; } //Player update (60fps) //left, right, up, and down are determined by keypress/keyrelease events void Player::update(){ int spd = 2; RECTANGLE prect; prect.left = this->x; prect.top = this->y; prect.right = this->x + this->size; prect.bottom = this->y + this->size; //Detect if we haven't hit anything (or in this case, are going to //because speed is a factor. //If we aren't going to hit anything, let the player keep moving //in that direction if (left) {if (!(place_meeting(-spd,0, prect))) {x -= spd;}} if (right) {if (!(place_meeting(spd,0,prect))) {x += spd;}} if (up) {if (!(place_meeting(0,0-spd,prect))) {y -= spd;}} if (down) {if (!(place_meeting(0,0+spd,prect))) {y += spd;}} } I detect for the collision using my version of a Game Maker function called: place_meeting(). It simply detects (with an offset), if my players rectangle is going to intersect with a blocks rectangle, given my speed as an offset. And if it is, I stop letting my player move in that direction.   Works like a charm.
  5. BurdenJohn

    Topdown wall collision, not working

      Well now I'm trying it your way as I'm more comfortable with this method, can't be looking through tons of code right now to solve this simple task.   Unfortunately, I'm still getting stuck along the edges, even when I check against what directions I'm going.   Here's a picture showing what's happening now for the following cases I'm testing (I only test two cases for now since there's no point in going forward if my player is all ready getting stuck):   Currently right now I have the following cases: - Player is going up but NOT left or right (only going up) - Player is going up AND left, but not right (up and left)   Even with just two cases so far, the player is all ready getting stuck..   If my player is going up and left, and he's colliding against the right side of the block, its smooth! Perfect, right?   If my player is going up, I'm only checking collision against the bottom of the block, it works! Perfect, right? Well if my player is going up and left and he's colliding against the bottom of the blocks, as he glides to the left across the bottom of the blocks, he gets stuck on the edges between the two blocks. (x = brect.right + 1)   This is bad, and it's the exact same thing that was happening before.   Here are my collision functions: //player right collides with box left bool SFMLPlayer::check_pright_bleft(RECTANGLE* _prect, RECTANGLE* _brect, int move_speed){ RECTANGLE prect = *_prect; RECTANGLE brect = *_brect; int offset = move_speed; if(prect.right > brect.left && prect.right <= brect.left + offset){ if ( (prect.top >= brect.top && prect.top < brect.bottom) ){ return true; } else if ( (prect.bottom >= brect.top && prect.bottom < brect.bottom) ){ return true; } } return false; } //player left collides with box right bool SFMLPlayer::check_pleft_bright(RECTANGLE* _prect, RECTANGLE* _brect, int move_speed){ RECTANGLE prect = *_prect; RECTANGLE brect = *_brect; int offset = move_speed; if(prect.left < brect.right + offset && prect.left > brect.right - offset){ if ( (prect.top >= brect.top && prect.top < brect.bottom) ){ return true; } else if ( (prect.bottom >= brect.top && prect.bottom < brect.bottom) ){ return true; } } return false; } //player bottom collides with box top bool SFMLPlayer::check_pbottom_btop(RECTANGLE* _prect, RECTANGLE* _brect, int move_speed){ RECTANGLE prect = *_prect; RECTANGLE brect = *_brect; int offset = move_speed; if(prect.bottom > brect.top && prect.bottom <= brect.top + offset){ if( (prect.right >= brect.left && prect.right < brect.right) ){ return true; } else if( (prect.left >= brect.left && prect.left < brect.right) ){ return true; } } return false; } //player top collides with box bottom bool SFMLPlayer::check_ptop_bbottom(RECTANGLE* _prect, RECTANGLE* _brect, int move_speed){ RECTANGLE prect = *_prect; RECTANGLE brect = *_brect; int offset = move_speed; if(prect.top < brect.bottom && prect.top >= brect.bottom - offset){ if( (prect.right >= brect.left && prect.right < brect.right) ){ return true; } else if( (prect.left >= brect.left && prect.left < brect.right) ){ return true; } } return false; } And here is where I'm using the test cases, inside the block iteration (looping through all blocks in the vector):   for(std::vector<Block>::iterator block = blocks->begin(); block != blocks->end(); ++block) { RECTANGLE prect; prect.left = this->x; prect.top = this->y; prect.right = this->x + this->size; prect.bottom = this->y + this->size; RECTANGLE brect; brect.left = block->x; brect.top = block->y; brect.right = block->x + block->size; brect.bottom = block->y + block->size; //AABB collision approach int offset = move_speed; //We are ONLY going up, check the top of player against bottom of block if(up && !right && !left){ if( check_ptop_bbottom(&prect, &brect, move_speed) ){ y = brect.bottom+1; } } //We are going UP AND LEFT, check the left side of player against right side of block, //AND also check the top of player against bottom of block (we could be on the right side or bottom side of the block) else if(up && (left && !right)){ if( check_pleft_bright(&prect, &brect, move_speed) ){ x = brect.right + 1; } else if( check_ptop_bbottom(&prect, &brect, move_speed) && prect.top > brect.top ){ y = brect.bottom; } } } Does anyone have any insight as to why my player gets stuck while gliding to the left along the bottom of the blocks, yet he does not get stuck while gliding up along the right side of the blocks?   Where in my collision code, or even my test case code, is it allowing the player to stop moving to the left when he's on the bottom of the blocks and pushing up? I've spent way too long on this and its unfortunately blocking me from doing any other work.   I've tried everything from changing an "<=" to an "<", placing offsets in different places, I just can't figure out how to make it so I can smoothly glide across all sides. There's something wrong in my collision code and its incredibly hard to detect.
  6. Currently developing a game in C++. My server (in C++) holds a list of players that are connected.   Players in this list can be either pushed or popped off the list. Each player has a unique ID that they hold throughout the game.   The id is actually their place in the list.   For example some pseudo code:   List<Player> players = new List(); players.add(new Player("Todd", players.getThisListPosition())); players.add(new Player("Ricky", players.getThisListPosition())); players.add(new Player("Bob", players.getThisListPosition())); players.add(new Player("Tim", players.getThisListPosition())); players.add(new Player("Anna", players.getThisListPosition())); For each player, their position in the list is their id. (assuming players.getThisListPosition() sets their ID as their position in the list).   Assume that the players were added when they contacted the server. The list looks like so:   players [0] = Todd [1] = Ricky [2] = Bob [3] = Tim [4] = Anna   Assuming the values of the list are the player instances in memory.   Now lets say Ricky leaves, players.pop( getID(playerThatLeft() ) ); The list looks like this now: [0] = Todd [1] = null [2] = Bob [3] = Tim [4] = Anna   ^This is ideal. This is what I want. However in reality the list would look like this:   [0] = Todd [1] = Bob [2] = Tim [3] = Anna   ^This is not what I want.   I want to retain the players positions in the list as they originally were. I don't want the list order to be modified. Is there anything in C++ that I can use that will do this?  
  7. I've got a bit of an issue.   Two graphic artists who I have hired to be payed for their work require contracts for our agreement. Both my graphic artists (who are working on separate projects from each other), and I, have agreed to our terms.   I now need a contract for our terms, however, I've never written a contract before and I don't know how or where to find one that fits the needs of our agreements.   To start off, I'm a Canadian. I haven't asked my artists where they are from yet, but I'm not sure if this matters to the contract(s).   For my first artist, I require a contract that contains the following terms: - The artist is to be paid XX amount in dollars after all required work is finished (after all graphic art assets are done) - The artist will receive a 35% profit share from all profits made from the game - If the artist is to cease communication with the programmer (myself), all of the money that was promised will not be issued, due to the fact that not all work was done and the graphic artist has failed to communicate with the programmer - I gain full copyright to the art assets that are made, allowing the artist to freely post them on a portfolio for hiring needs   For my second artist, I require a contract that contains the following terms: - The artist is to be paid XX amount in dollars after all required work is finished (after all graphic art assets are done) - The artist will not receive a profit share - If the artist is to cease communication with the programmer (myself), all of the money that was promised will not be issued, due to the fact that not all work was done and the graphic artist has failed to communicate with the programmer - I gain full copyright to the art assets that are made, allowing the artist to freely post them on a portfolio for hiring needs   I have had multiple artists stop communication with me during projects, forcing me to quit projects that I was hoping to be finished. So now that I'm offering money and that I will soon have contracts, I'm hoping that this will stop.   I have no legal background, so I am stumped on where I can find contracts that will suit these needs. Is it possible to have a contract like this?   If it is, please direct me to where I can find some kind of a contract template that I can officially and legally use for these artists, in which both myself and they are required to sign and scan digitally.
  8. BurdenJohn

    Topdown wall collision, not working

    I'm sorry I just couldn't get your rectangle_collision_x/y() functions working. I'm extremely close now though, but still stuck.   Here's my current collision code: for(std::vector<Block>::iterator block = blocks->begin(); block != blocks->end(); ++block) { RECTANGLE prect; prect.left = this->x; prect.top = this->y; prect.right = this->x + this->size; prect.bottom = this->y + this->size; RECTANGLE brect; brect.left = block->x; brect.top = block->y; brect.right = block->x + block->size; brect.bottom = block->y + block->size; //AABB collision approach int deca = 3; //PLAYER RIGHT TOUCHES BOX LEFT //Check if player right side touches box left side if( (prect.right + move_speed >= brect.left) && (prect.right + move_speed < brect.left + move_speed*deca) ){ //Check if we are within the vertical value of the left side if ( (prect.top >= brect.top && prect.top <= brect.bottom) || (prect.bottom >= brect.top && prect.bottom <= brect.bottom) ){ x = brect.left-size-move_speed/(deca-1); //continue; } } //PLAYER LEFT TOUCHES BOX RIGHT //Check if player left side touches box right side else if( (prect.left - move_speed <= brect.right) && (prect.left - move_speed > brect.right - move_speed*deca) ){ //Check if we are within the vertical value of the right side if ( (prect.top >= brect.top && prect.top <= brect.bottom) || (prect.bottom >= brect.top && prect.bottom <= brect.bottom) ){ x = brect.right+move_speed/(deca-1); //continue; } } //PLAYER BOTTOM TOUCHES BOX TOP //Check if player bottom side touches box top side else if( (prect.bottom + move_speed >= brect.top) && (prect.bottom + move_speed < brect.top + move_speed*deca) ){ //Check if we are within the horizontal value of the bottom side if( (prect.left >= brect.left && prect.left <= brect.right) || (prect.right >= brect.left && prect.right <= brect.right) ){ y = brect.top-size-move_speed/(deca-1); //continue; } } //PLAYER TOP TOUCHES BOX BOTTOM //Check if player top side touches box bottom side else if( (prect.top - move_speed <= brect.bottom) && (prect.top - move_speed > brect.bottom - move_speed*deca) ){ //Check if we are within the horizontal value of the bottom side if( (prect.left >= brect.left && prect.left <= brect.right) || (prect.right >= brect.left && prect.right <= brect.right) ){ y = brect.bottom+move_speed/(deca-1); //continue; } } } So what's happening now is, the sides are perfect! I can glide across the sides very easily!   Now let's say the top of my player (prect.top) is touching the bottom of the wall of blocks. I can glide to the right, though when it hits edges, it jitters a bit, but it still glides, but the jitterness still needs to be fixed. However if I glide to the left and I hit edges, the player stops.   The same as when the bottom of my player (prect.bottom) is touching the top of the wall of blocks (brect.top), gliding to the right works, but jittery (not smooth) when it hits edges, gliding to the left, when you hit an edge, player stops.   My top and bottom block collision checks are under the following comments: //PLAYER BOTTOM TOUCHES BOX TOP   and   //PLAYER TOP TOUCHES BOX BOTTOM   EDIT: I just noticed that since the player is stopping in the x-coordinate, the two statements that are causing it are the ones under these comments: //PLAYER RIGHT TOUCHES BOX LEFT //PLAYER LEFT TOUCHES BOX RIGHT   I'm extremely close to finally getting it perfect, just need to fix: - Jitterness when gliding to the right against bottom/top of blocks, only when the player hits the edges of a block - The player stopping when gliding to the left against bottom/top of blocks, only when the player hits the edges of a block   Does anyone know, possibly through the two specified if statements under those two comments I mentioned, what could be causing it and how to fix it?   I've tried a large combination of things. One thing I did to fix my problem from before was, I change all of the if's to else-ifs.
  9. BurdenJohn

    Topdown wall collision, not working

    Hmm it didn't seem to work. I'm now trying the AABB approach:   for(std::vector<Block>::iterator block = blocks->begin(); block != blocks->end(); ++block) { RECTANGLE prect; prect.left = this->x; prect.top = this->y; prect.right = this->x + this->size; prect.bottom = this->y + this->size; RECTANGLE brect; brect.left = block->x; brect.top = block->y; brect.right = block->x + block->size; brect.bottom = block->y + block->size; int deca = 3; //PLAYER RIGHT TOUCHES BOX LEFT //Check if player right side touches box left side if( (prect.right + move_speed >= brect.left) && (prect.right + move_speed < brect.left + move_speed*deca) ){ //Check if we are within the vertical value of the left side if ( (prect.top >= brect.top && prect.top <= brect.bottom) || (prect.bottom >= brect.top && prect.bottom <= brect.bottom) ){ x = brect.left-size-move_speed/(deca-1); //continue; } } //PLAYER LEFT TOUCHES BOX RIGHT //Check if player left side touches box right side if( (prect.left - move_speed <= brect.right) && (prect.left - move_speed > brect.right - move_speed*deca) ){ //Check if we are within the vertical value of the right side if ( (prect.top >= brect.top && prect.top <= brect.bottom) || (prect.bottom >= brect.top && prect.bottom <= brect.bottom) ){ x = brect.right+move_speed/(deca-1); //continue; } } //PLAYER BOTTOM TOUCHES BOX TOP //Check if player bottom side touches box top side if( (prect.bottom + move_speed >= brect.top) && (prect.bottom + move_speed < brect.top + move_speed*deca) ){ //Check if we are within the horizontal value of the bottom side if( (prect.left >= brect.left && prect.left <= brect.right) || (prect.right >= brect.left && prect.right <= brect.right) ){ y = brect.top-size-move_speed/(deca-1); //continue; } } //PLAYER TOP TOUCHES BOX BOTTOM //Check if player top side touches box bottom side if( (prect.top - move_speed <= brect.bottom) && (prect.top - move_speed > brect.bottom - move_speed*deca) ){ //Check if we are within the horizontal value of the bottom side if( (prect.left >= brect.left && prect.left <= brect.right) || (prect.right >= brect.left && prect.right <= brect.right) ){ y = brect.bottom+move_speed/(deca-1); //continue; } } } Unfortunately, this seems to work only for blocks that are alone and not touching another.   If I place a line of blocks, and my player starts gliding along it (say, the top of my player glides along the bottom of the line of blocks), once my player hits the edge of a block, he stops.   This is taking me way longer than it should, I should all ready be coding other parts of the game, but this is completely blocking me.
  10. BurdenJohn

    Topdown wall collision, not working

    Hmm changing my IntersectRect() code to that seems to make my player go through all walls now:   bool SFMLPlayer::IntersectRect(RECTANGLE* r1, RECTANGLE* r2) { return ! ( r2->left > r1->right || r2->right < r1->left || r2->top < r1->bottom || r2->bottom > r1->top ); } EDIT: All right well I have a better intersection code now, my player finally detects collisions against the walls and doesn't go through them, however I can't glide across them, my player just gets stuck when I push against the normal of the side of the wall.   Here's my new rectangle intersection code: bool rectangle_collision(float x_1, float y_1, float width_1, float height_1, float x_2, float y_2, float width_2, float height_2) { return !(x_1 > x_2+width_2 || x_1+width_1 < x_2 || y_1 > y_2+height_2 || y_1+height_1 < y_2); } And my for loop using it (with the old intersection function call commented out): for(std::vector<Block>::iterator block = blocks->begin(); block != blocks->end(); ++block) { RECTANGLE prect; prect.left = this->x + hmove; prect.top = this->y + vmove; prect.right = prect.left + this->size; prect.bottom = prect.bottom + this->size; RECTANGLE brect; brect.left = block->x; brect.top = block->y; brect.right = block->x + block->size; brect.bottom = block->y + block->size; /* if(IntersectRect(&prect, &brect)){ place_meeting = true; break; } */ if(rectangle_collision(prect.left, prect.top, 32, 32, brect.left, brect.top, 32, 32)){ place_meeting = true; break; } } Now by stuck, I mean when I move up to a side of one of the blocks, I can't move anywhere else except the normal (opposite direction to which I'm facing). Once I move that way, I'm free to move again until I meet a side of the block again.   For example, if my player is moving to the bottom side of a block, and it hits that side, I can't move left or right. The only direction I can move is down. Once I move down, I'm free to move anywhere I want until I hit another side again.   If I hit the left side of a block (the right side of my player hitting the left side of a block), I can't move up or down, I can only move left to free myself.   And so on.   Not sure why this is happening, but I'm close. Just need to be able to glide across the sides.
  11. Thanks for the information everyone.
  12. Is it at all possible to just write out the terms of the contract, as I've done on this topic, and just put a place for two signatures between the two participants? Or would that not be a legal contract?
  13. Thank you all for the suggestions. I'm going to go with Giallanon's suggestion, was very simple and it works!   Thanks guys.
  14. Honestly this was the simplest solution! Just a quick question though, here's my removePlayer function:   int PlayerList::removePlayer(unsigned int id){ //std::cout << "===REMOVING PLAYER===" << std::endl; if(players[id] != NULL){ delete players[id]; players[id] = NULL; } return 0; } It works when I remove the line "delete players[id];" For some reason when I leave that in, I get an exception when I try to execute removePlayer(2) for example. It says the heap gets corrupted.   Why is that? And also, why do I need to delete that piece of memory, because when I set it to NULL, the reference is gone anyways? Or would the player instance still be in memory? If that's the case, how do I get around this issue where it corrupts the heap?
  15. Mmm I could only find one that was close to what I wanted: https://www.docracy.com/5843/commissioned-illustration-offer-short-easy   However it doesn't cover the fact that: - The price of the agreement is to be paid in full after the job is done, this states before - It doesn't talk about profit-share   As for the list of game attorneys, are there any free ones out there?
  16. The thing is the error comes from File: "xmemory0" at line 617: #define _ALLOC_MEMBER_CONSTRUCT( \ TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, CALL_OPT, X2, X3, X4) \ template<class _Objty COMMA LIST(_CLASS_TYPE)> \ void construct(_Objty *_Ptr COMMA LIST(_TYPE_REFREF_ARG)) \ { /* construct _Objty(_Types...) at _Ptr */ \ ::new ((void *)_Ptr) _Objty(LIST(_FORWARD_ARG)); \ } _VARIADIC_EXPAND_0X(_ALLOC_MEMBER_CONSTRUCT, , , , ) #undef _ALLOC_MEMBER_CONSTRUCT Also, commenting out push_back() seemed to get the error away, but of course I still need that in (caused an exception). So I tried your emplace_back() suggestion, and I get the same error as before (cannot access private member...) line 617 of file xmemory0 as posted above. Here's my playerList.cpp code as it stands: http://pastie.org/private/0lhdxjoczzjfdg2acyzq   Does it seem like my list would work though using these methods?
  17. Hmm not sure what's going on here, but now I'm trying to use std::unique_ptr but I'm getting a private member access error? #include "playerList.h" void PlayerList::printList(){ std::cout << "PRINTING PLAYER LIST" << std::endl; for(std::vector<std::unique_ptr<Player>>::iterator it = playList.begin(); it != playList.end(); ++it) { Player* p = it->get(); std::cout << '[' << p->id << ']' << p->name << std::endl; } } void PlayerList::addPlayer(Player* p){ std::cout << "ATTEMPTING TO ADD PLAYER: " << p->name << std::endl; std::unique_ptr<Player> uptr(p); unsigned int count = 0; unsigned int nullCount = 0; //Check for a null player, if we find one, replace it with the new one for(std::vector<std::unique_ptr<Player>>::iterator it = playList.begin(); it != playList.end(); ++it) { count++; Player* ps = it->get(); if(it->get() == nullptr){ nullCount++; unsigned int pos = it - playList.begin(); it->swap(uptr); it->get()->id = pos; return; } } //If we didn't find a null player unsigned int pos = playList.size(); uptr->id = pos; playList.push_back(uptr); } void PlayerList::removePlayer(unsigned int id){ for(std::vector<std::unique_ptr<Player>>::iterator it = playList.begin(); it != playList.end(); ++it) { Player* p = it->get(); if(p->id == id){ std::cout << "REMOVING PLAYER: " << p->name << std::endl; it->reset(); } } }   The idea now is that when I add a player, I check for any null players that are in the list.   If I find one, I make swap the null player with the new player I'm adding, and the new player gets the id that's equal to the current position of the iteration ( it - playList.begin() )     A null player is now a player that, when it gets removed, its unique_ptr is reset().   Not sure if this works though, can't figure out why I'm getting that error. I've read that it has to do with making a copy? I don't recall ever making a copy of the unique_ptr?
  18. Well I'm off to an okay start. Made a custom list class that uses a vector.   So far when I add players, their ids are fine. When I remove a player, the players still retain their ids, which is fine, however after removing a player and then adding a new player, the player does not fill the position of the one that was previously removed.   Example:   push_back josh, tod, bob, tim, steph, giorgio.   [0] Josh [1] Tod [2] Bob [3] Tim [4] Steph [5] Giorgio   remove bob List now prints:   [0] Josh [1] Tod [3] Tim [4] Steph [5] Giorgio   push_back Greg   List now prints: [0] Josh [1] Tod [3] Tim [4] Steph [5] Giorgio [5] Greg   The reason why 5 is repeated is because the id that is assigned to the player is based on the size of the list. However I need it so the ID is based on the position that it fills, but currently the vector isn't filling the list, its just pushing it to the back. Not sure how to fill empty slots (in this case, position 2 was supposed to be assigned to greg).   playerList.h #include <vector> #include "player.h" #include <iostream> #pragma once class PlayerList{ std::vector<Player> playList; //the list public: void addPlayer(Player* p); //adds Player p void removePlayer(unsigned int id); //removes player given id Player getPlayer(unsigned int id); //gets player given id void printList(); }; playerList.cpp #include "playerList.h" void PlayerList::printList(){ for(std::vector<Player>::iterator it = playList.begin(); it != playList.end(); ++it) { std::cout << "[" << it->id << "] " << it->name << std::endl; } } void PlayerList::addPlayer(Player* p){ //std::cout << "ADDING PLAYER, LIST SIZE: " << playList.size() << std::endl; unsigned int theId = playList.size(); p->id = theId; playList.push_back(*p); std::cout << "ADDING PLAYER, theId: " << theId << std::endl; } void PlayerList::removePlayer(unsigned int id){ for(std::vector<Player>::iterator it = playList.begin(); it != playList.end(); ++it) { if(it->id == id){ playList.erase(it); } } } One thing I could do, is when adding a player, check the list for any blank spots that aren't filled, but how do I do this? When I remove a player, how would I mark its position in the list as "blank" rather than just erase it completely?
  19. I'm a bit confused on how else you would send movement without sending keypresses? How else would the server know that a player is moving to the left, if you don't tell it that you pressed the left key?   How is this wasteful?   Also, are you saying that having multiple instances of Match in one process, is probably not a good idea, and its better to have a separate process for each Match? You also said that when you have multiple processes of the Server, you need a new port. Wouldn't you need to port forward for every single new server instance?    Let's say you port forward 12345 TCP, 123456 UDP. Now a new server instance is created, you need to port forward two new ports, but how would you do this when you would need to manually go to the router settings and port forward?   Or are you saying, have a preset range of ports to be forwarded? Which is kind of strange because you won't know how many Matches there would be depending on the popularity of the game. You would be limited based on how large of a range of ports you want to forward. It makes more sense for their to be a master server that handles all the network communication on two main ports (TCP and UDP), and the information is relayed to the Match instances and the Match instances can send information back to the master server and have the master server send out data.   The master server in other words would be in charge of networking, and the Matches would retrieve the network data from the server, and send it back to the server to be sent out to the designated clients.
  20. Hello.   I've always wondered this on my mind and I've had a hard time looking for papers or articles on how this is done exactly. Take for example the game: GunZ: http://mmohuts.com/wp-content/gallery/gunz/gunz-game-lobby.jpg?ec9f9b   In this game you can connect to a certain number of servers after you've logged in. Once you're logged in, you're connected to the lobby where you can chat with other players connected to the main server.   However, you can also create your own "rooms" and "host" your own game for others to play on.   Now it's not 100% for sure that anyone here may know how exactly GunZ does it, but does anyone have an idea on how this actually works?   When a player hosts a room, and someone wishes to join your room, are other people connecting to that player? But that player hasn't even port forwarded and they're managing to connect to him anyways, are they using some sort of UDP holepunch / NAT traversal?    Are players technically actually hosting their own servers for other players to connect to? Because if that's the case isn't this a huge security risk since they can simply just edit memory on their server?   If they aren't indeed hosting their own servers (rooms), then does that mean every single room on the server is being emulated through the main server? Meaning when you connect to a players room, you're still actually sending datagrams/packets to the main server?
  21. When you say instances in-process, are you talking about instances of some sort of "server" class? And obviously 'new process' I'm assuming would be just multiple processes of servers.   But would you be using the same socket for each? Or different sockets? What about ports? Would each "instance" be using a different port?   What if the game was insanely popular and it had a TON of rooms (hundreds) of rooms. Wouldn't the server need to port forward all of those ports if they all use different ports? And if so, isn't that a huge security risk?   In your other case, where the players themselves have the server running through a NAT holepunch method, what exactly can a developer do to prevent the players from manipulating data in their servers to better themselves in the game? (e.g. increasing their score)
  22. Let's say you want to make a real-time game, perhaps a 2D topdown game. Things you would do in the game to keep it simple are:   - Connect to the server - Move the player with the keys - Possibly press space bar to attack - Send a chat message   But what would happen if a datagram from any of these situations get lost? What would you do?   1. Connecting to the server . If you send a UDP datagram to the server, the server would take your IP and port and then create a player based on an ID it gives you, this it how it identifies you every time it receives a datagram from you.   But what if upon "connection" (not actually a connection, just a udp datagram that says 'make me a part of your server'), this initial datagram gets lost. Is it right to say that you would just resend it if after a certain period of time you did not receive a reply back from the server?   2. Moving the player/attacking If at any time we move the player/press a movement key/attack key, we would send a keystroke to the server telling it what key we pressed/released. The server would then relay this to all the other clients.   But what if this keystroke datagram gets lost? Either upon client->server or server->clients. Because keystrokes are happening all the time, is it efficient to just resend it all the time? Or would we just ignore the fact that it got lost along the way because there's a chance that if you press a key again it will most likely make it the next time?   3. Sending a chat message This would be something that MUST reach the server. If it got lost along the way, after a certain period of time if we did not receive a reply from the other side/receiving end, do we re-send it?   Is it okay to just keep resending datagrams if we know after a certain period of time it did not reach? And also, what about confirming if a datagram got successfully sent?   If client sends a chat message to the server, and the server receives it, should the server send a reply back to the client to confirm that it received it? What would happen if that reply got lost, what then?  
  23. I'm trying to make a simple network game using a client and server. Currently I have two threads running for both my client and server: - The Main thread which calculates player positions, physics, draws things to the screen, etc. - The Client/Server thread which handles sending/receiving of datagrams from/to the server or from/to the client The reason I have two threads for each is because the receive() method call is BLOCKING, so I don't want it to block any of my gameplay while its waiting for a new datagram. This works absolutely fine until I get to the point where I want to be able to send a datagram in my main thread. EXAMPLE  In the client, in my main thread, I have a keypress event where when my client presses the 'z' key, it sends a datagram to the server as a test. However, the program just completely stalls, no exceptions. It stalls to the point where I need to close it via task manager in Windows. The socket I'm using to send to is declared and initialized in my ClientThread class (which extends Thread). It gets initialized when run() is called in my ClientThread: public void run() { try { // Construct the socket socket = new DatagramSocket(); ... I can easily send datagrams in my ClientThread/ServerThread, but when I try to send them in my MainThread at any given time (e.g. when a client presses Z and wants to send a test message), the program stalls/crashes. Why is it crashing and what can I do to fix this? Is it okay to use one thread for receiving/sending, and another thread for doing other calculations but also including sending datagrams at any given time? (e.g. when a player presses the 'z' key or something else).   I have a feeling it has something to do with the fact that the DatagramSocket is declared and initialized inside the ClientThread/ServerThread class and the MainThread is trying to gain access to it at any given time it wants (again, when a player presses the 'z' key for example).
  24. Hmm well thanks for all the help. I will try to use the BlockingQueue you suggested. In any case if anyone wants to take a stab at it, here's my implementation so far:   ClientThread.java: package Network;   import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.net.UnknownHostException; import java.util.logging.Level; import java.util.logging.Logger;   import java.net.*; import networkresearch.NetworkResearch; import utils.ByteHandle; import Network.NetworkBuffer; import networkresearch.Player;   public class ClientThread extends Thread {       public DatagramSocket socket;     public DatagramPacket packet;     public NetworkBuffer buffer;     private NetworkResearch ui;     private final static int PACKETSIZE = 100;     InetAddress host;     int serverport;       //byte[] dataBuffer;     public ClientThread(NetworkResearch observer) throws UnknownHostException {         this.ui = observer;         socket = null;         host = InetAddress.getByName("127.0.0.1");         serverport = Integer.parseInt("1024");         buffer = new NetworkBuffer();     }       /*      * Sends buffer to server      */     @Override     public void run() {         try {             // Construct the socket             socket = new DatagramSocket();             buffer.clearBuffer();             Integer pid = 0;             ui.console.println("BYTE: " + pid.byteValue());             NetworkUtils.writeByte(pid.byteValue(), buffer);             packet = new DatagramPacket(buffer.getData(), buffer.getData().length, host, serverport);             socket.send(packet);               // Set a receive timeout, 2000 milliseconds             //socket.setSoTimeout(2000);             // Prepare the packet for receive             while (true) {                 packet.setData(new byte[PACKETSIZE]);                   // Wait for a response from the server                 socket.receive(packet);                 buffer.clearBuffer(); // Clear the buffer of any previous data it had                 buffer.setData(packet.getData());                 // Message ID                 Byte b = NetworkUtils.readByte(buffer);                 int mid = b.intValue();                 ui.console.println("CLIENT MESID: " + mid);                 switch (mid) {                     case 0:                         ui.console.println("Server says welcome!");                           buffer.clearBuffer();                         NetworkUtils.writeByte(new Integer(1).byteValue(), buffer);                         DatagramPacket sendPacket = new DatagramPacket(buffer.getData(), buffer.getData().length, packet.getAddress(), packet.getPort());                         socket.send(sendPacket);                         break;                 }             }             } catch (Exception e) {             ui.console.println(e.toString());             ui.state = "menu";             ui.setPane(ui.mainPanel);         } finally {             if (socket != null) {                 socket.close();             }         }     }       public void stopClient() {         System.out.println("STOPPING CLIENT");         socket.close();         this.stop();     } }     ServerThread.java: package Network;   import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.SocketException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import networkresearch.NetworkResearch; import networkresearch.Player; import utils.ByteHandle;   public class ServerThread extends Thread {       private final static int PACKETSIZE = 100;     private NetworkResearch ui;     //DatagramPacket packet;     DatagramSocket socket;     NetworkBuffer buffer;       public ServerThread(NetworkResearch observer) {         this.ui = observer;     }       @Override     public void run() {         try {             buffer = new NetworkBuffer();             int port = Integer.parseInt("1024");             socket = new DatagramSocket(port);               ui.console.println("SERVER STARTED ON UDP PORT: " + port);                 while (true) {                 // Create a packet                 DatagramPacket packet = new DatagramPacket(new byte[PACKETSIZE], PACKETSIZE);                 // Receive a packet (blocking)                 socket.receive(packet);                 buffer.clearBuffer(); // Clear the buffer of any previous data it had                 buffer.setData(packet.getData());                 // Message ID                 Byte b = NetworkUtils.readByte(buffer);                 int mid = b.intValue();                 ui.console.println("SERVER MESID: " + mid);                 switch (mid) {                     //Initial connection packet                     case 0:                         Player player = new Player(ui.gamePanel, "goblin");                         ui.gamePanel.players.add(player);                           buffer.clearBuffer();                         NetworkUtils.writeByte(new Integer(0).byteValue(), buffer);                         DatagramPacket sendPacket = new DatagramPacket(buffer.getData(), buffer.getData().length, packet.getAddress(), packet.getPort());                         socket.send(sendPacket);                         break;                       case 1:                         ui.console.println("Client sends a response back!");                         break;                 }                 /*                  byte[] newData = "Hello Client".getBytes();                  DatagramPacket newPacket = new DatagramPacket(newData, newData.length, packet.getAddress(), packet.getPort());                  // Return the packet to the sender                  socket.send(newPacket);                  */             }         } catch (Exception e) {             System.out.println(e);         }     }       public void stopServer() {         System.out.println("STOPPING SERVER");         socket.close();         this.stop();     } }   GamePanel.java: package networkresearch;   import java.awt.Graphics; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.JTextField;   import Network.ClientThread; import Network.NetworkUtils; import Network.ServerThread; import java.awt.Dimension; import java.net.UnknownHostException; import javax.swing.JFrame;   public class GamePanel extends CorePanel {       NetworkResearch ui;     GameThread gameThread;     ClientThread clientThread;     ServerThread serverThread;     BufferedImage[] images_players;     public ArrayList<Player> players;     BufferedImage gameBackground;     long startTime = 0;     long endTime = 0;       GamePanel(NetworkResearch ui) throws IOException {         images_players = new BufferedImage[5];         images_players[0] = ui.loadAsset("player_knight.png");         images_players[1] = ui.loadAsset("player_goblin.png");         images_players[2] = ui.loadAsset("player_ogre.png");         images_players[3] = ui.loadAsset("player_skeleton.png");         images_players[4] = ui.loadAsset("player_wolf.png");         this.ui = ui;         JTextField nameField = new JTextField("Test Player");         nameField.setColumns(6);         //add(nameField);           gameBackground = ui.loadAsset("gameBackground.png");         players = new ArrayList();     }       @Override     public void keyTyped(KeyEvent e) {     }       @Override     public void keyPressed(KeyEvent e) {         if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {             goBackToMenu();         }           if (e.getKeyChar() == 'z') {             ui.console.println("SENDING FROM CLIENT TO SERVER!");             /**              * THIS IS WHERE THE GAME WILL CRASH! ATTEMPTING TO SEND A DATAGRAM              * OUTSIDE OF THE ClientThread CLASS!              */             try {                 int x = 5, y = 10;                 clientThread.buffer.clearBuffer();                 NetworkUtils.writeInt(x, clientThread.buffer);                 // Send it                 clientThread.socket.send(clientThread.packet);             } catch (IOException ex) {                 Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex);             }           }           for (Player player : players) {             switch (e.getKeyChar()) {                 case 'a':                     player.keyLeft = true;                     break;                 case 's':                     player.keyDown = true;                     break;                 case 'd':                     player.keyRight = true;                     break;                 case 'w':                     player.keyUp = true;                     break;                 case ' ':                     player.keySpace = true;                     break;             }         }     }       @Override     public void keyReleased(KeyEvent e) {         for (Player player : players) {             switch (e.getKeyChar()) {                 case 'a':                     player.keyLeft = false;                     break;                 case 's':                     player.keyDown = false;                     break;                 case 'd':                     player.keyRight = false;                     break;                 case 'w':                     player.keyUp = false;                     break;                 case ' ':                     player.keySpace = false;                     break;             }         }     }       @Override     protected void paintComponent(Graphics g) {         super.paintComponent(g);         g.drawImage(gameBackground, 0, 0, this);         for (Iterator<Player> it = players.iterator(); it.hasNext();) {             it.next().paint(g);         }     }       @Override     public void start() {         gameThread = new GameThread(this);         try {             clientThread = new ClientThread(ui);         } catch (UnknownHostException ex) {             Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex);         }         serverThread = new ServerThread(ui);         this.setFocusable(true);         gameThread.start();         if (ui.state.equals("inserver")) {             ui.setTitle("SERVER");             serverThread.start();             ui.console.setTitle("Console: Server");         } else if (ui.state.equals("inclient")) {               Player player = new Player(this, "goblin");             players.add(player);               ui.setTitle("CLIENT");             clientThread.start();             ui.console.setTitle("Console: Client");         }         startTime = new Date().getTime();     }       public void update() {         for (Iterator<Player> it = players.iterator(); it.hasNext();) {             it.next().update();         }     }       public void goBackToMenu() {         System.out.println("GOING BACK TO MENU");         ui.state = "menu";         ui.setPane(ui.mainPanel);         ui.curPanel.repaint();     }       @Override     public void stop() {         if (gameThread.isAlive()) {             gameThread.stop();         }         if (clientThread.isAlive()) {             clientThread.stopClient();         } else if (serverThread.isAlive()) {             serverThread.stopServer();         }     } }   The game stalls/crashes in GamePanel.java at the try/catch block (its commented).
  25.   I think that's my fault.  Linking you to the NIO server isn't good if you've never done anything like that before.  How much time do you have to get this working?  If you have time and are really trying to understand how to make a networked game, then you need to understand the two principles seperatly before trying to put them together.   One type of application used for learning/studying/understanding networked applications is a simple chat server.  If you can get that working, you're well on your way.  A lot of the same problems you'll encounter in a game will come up with a chat server.   1.  Coding a server to listen for multiple clients. 2.  What does the server do when clients disconnect? 3.  How does a client connect to the server? 4.  How does the client send chat messages? 5.  How does the client receive message from other clients? 6.  How does the server communicate who's in the chat room? 7.  What do clients do if the server disconnects?   The great thing about a chat room is that the GUI isn't hard, and the messages are just text, and it seems really easy.  But try one, and then setup a server, and send it to a few friends, and see what happens.   Well what I've currently got right now is basically I'm trying to be able to have functions like so when it comes to sending/receiving messages: clearbuffer(); writebyte(1); //Message ID writestring("John"); writeint(5); send(datagramSocket);   On the other end:   switch(readbyte()){     case 1:     String name = readstring();     int x = readint(); }   And so far this is working out great. However I can only do this inside the NetworkThread.   Even for a simple chat system, I would want to be able to press a button "Send" that sends text from the GUI JTextField. But the button press event for the "Send" button is triggered inside the Main Thread. In this case, as what's happening currently, the game will halt.   Should I just have three threads? Main Thread NetworkSendThread NetworkReceiveThread   Or should I just use one thread: Main Thread and instead of using a DatagramSocket which is blocking, I would use this socket: http://www.eecs.harvard.edu/~mdw/proj/java-nbio/javadoc/seda/nbio/NonblockingDatagramSocket.html   A huge advantage in terms of simplicity is that I can have my main game loop, and network loop all in one thread.   Right now I have two problems: - How would I get my Main Thread to communicate with my NetworkThread, e.g. When the player presses the 'z' key, somehow trigger an event in the NetworkThread telling that I've done so, and then the NetworkThread would take care of sending the data through the network using its DatagramSocket.   - How on earth do I do sending/receiving on two separate threads? Would both of those threads need to somehow share the DatagramSocket?
  • 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!