tag:blogger.com,1999:blog-17927341229802754902024-02-22T22:12:28.100+01:00The JBF ProjectRandom thoughts about IT worldAnonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.comBlogger55125tag:blogger.com,1999:blog-1792734122980275490.post-58754124452300013672015-12-17T22:27:00.001+01:002015-12-17T22:27:16.428+01:00Arduino ConsoleEverybody needs some time to do nothing,<br />
I mean not do things because you need to do,<br />
but instead to do things just to free your mind<br />
<br />
I like to code, and I like electronics so I started wondering which options were in the market to be able perform my own ´experiments´ so after some research I end up with two finalists:<br />
<br />
<ul>
<li>RaspberryPI</li>
<li>Arduino</li>
</ul>
<br />
Raspberry is awesome in many senses but it adds an additional layer of complexity which discoraged me to take it so I finally end buying an Arduino Nano ´Chinese clone´ for 2$, yes you are reading right, 2$!, I also bought several components to perform experiments: electric resistances, leds lights, a pair of stepper motors, ultrasound sensor, buttons, a joystick, and a pair of TFT screens , each one for about 6-8$ (1.8inches and 2.4 inches).. I felt really like stealing...<br />
<br />
I decided to play with the idea of actualy building my own ´Hardware´ gaming box, so I performed all these steps:<br />
<br />
<br />
<ol>
<li>Attach Arduino Nano board to a breadboard</li>
<li>Attach the 1.8 Inches TFT screen to the breadboard</li>
<li>Connect Arduino power-out pins to power lines in the breadboard</li>
<li>Connect TFT pins with Digital data pins D8,D9,D10,D11 and D13</li>
<li>Connect the joystick to Analog pins A0 and A1</li>
</ol>
<br />
And the final hardware setup:<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0zH5ECGru8SpzgZ7oR3LH6nv-orXyJYJGnMkBZxkFQGUqfRdplYcGaeHGivHPZgLJ0oK3XnerocE5XZl_ExG_kPgQ4iNMxAnHGKenMk8H8qN23SmjWiaS1eBebm9P5goId_1gR3ss-6rC/s1600/overview.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0zH5ECGru8SpzgZ7oR3LH6nv-orXyJYJGnMkBZxkFQGUqfRdplYcGaeHGivHPZgLJ0oK3XnerocE5XZl_ExG_kPgQ4iNMxAnHGKenMk8H8qN23SmjWiaS1eBebm9P5goId_1gR3ss-6rC/s640/overview.jpg" width="507" /></a><br />
<br />
<br />
Details for the Nano pin connections<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJEV3VFlSmFwbFZH7yK3bNyQ9pLfRj5ZmvRXqKUreHC5V4sHxuouL8v8fSCi-KM8gYmr33twbw8ia37HQU5GJKg9BUwa24nbAtQqJTrrC6rg1Wc_4zQXMxYqyvNURe1fJCz-ftd8mo_DF_/s1600/arduino.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="428" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgJEV3VFlSmFwbFZH7yK3bNyQ9pLfRj5ZmvRXqKUreHC5V4sHxuouL8v8fSCi-KM8gYmr33twbw8ia37HQU5GJKg9BUwa24nbAtQqJTrrC6rg1Wc_4zQXMxYqyvNURe1fJCz-ftd8mo_DF_/s640/arduino.png" width="640" /></a></div>
<br />
And for the joystick Pins:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYl1pAykQg9-SKXlfv4p7h3dRLGmy-h_K4qxZ4DZ5Ii7lIQTbQvSVhbcWzfsXG2L31d9zcQ293TS6szc6LGJVO_-DTynLKvHhljXp10BYRUpo6SjI5pkn9d761rgrrjWcWCR37myXFAUDF/s1600/joystick.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="424" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhYl1pAykQg9-SKXlfv4p7h3dRLGmy-h_K4qxZ4DZ5Ii7lIQTbQvSVhbcWzfsXG2L31d9zcQ293TS6szc6LGJVO_-DTynLKvHhljXp10BYRUpo6SjI5pkn9d761rgrrjWcWCR37myXFAUDF/s640/joystick.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Connecting the TFT screen involved a little research as all components came without documentation, but hey Google is always your friend! I end up in a web page from a guy who made the device work and kindly shared how to setup the cables:<br />
<br />
<a href="http://blog.simtronyx.de/en/a-1-8-inch-tft-color-display-hy-1-8-spi-and-an-arduino/">http://blog.simtronyx.de/en/a-1-8-inch-tft-color-display-hy-1-8-spi-and-an-arduino/</a><br />
<span id="goog_562554708"></span><span id="goog_562554709"></span><a href="https://www.blogger.com/"></a><br />
<table style="background-color: white; border-bottom-color: rgb(237, 237, 237); border-bottom-style: solid; border-collapse: collapse; border-spacing: 0px; border-width: 0px 0px 1px; color: #757575; font-family: 'Open Sans', Helvetica, Arial, sans-serif; font-size: 0.857143rem; line-height: 24px; margin: 0px 0px 1.71429rem; padding: 0px; vertical-align: baseline; width: 623px;"><tbody style="border: 0px; font-size: 12px; margin: 0px; padding: 0px; vertical-align: baseline;">
<tr class=".list_header" style="background-color: #fafafa; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;"><strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">Arduino (Mini, Nano, Uno)</strong></td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;"><strong style="border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;">HY-1.8 SPI</strong></td></tr>
<tr style="background-color: #fefefe; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">D9</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 07 (A0)</td></tr>
<tr style="background-color: #fafafa; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">D10 (SS)</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 10 (CS)</td></tr>
<tr style="background-color: #fefefe; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">D11 (MOSI)</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 08 (SDA)</td></tr>
<tr style="background-color: #fafafa; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">D13 (SCK)</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 09 (SCK)</td></tr>
<tr style="background-color: #fefefe; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">D8</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 06 (RESET)</td></tr>
<tr style="background-color: #fafafa; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">5V (VCC)</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 02 (VCC)</td></tr>
<tr style="background-color: #fefefe; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">GND</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 01 (GND)</td></tr>
<tr style="background-color: #fafafa; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">3.3V or 5V (VCC)</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 15 (LED+)</td></tr>
<tr style="background-color: #fefefe; border: 0px; margin: 0px; padding: 0px; vertical-align: baseline;"><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">GND</td><td style="border-left-color: rgb(237, 237, 237); border-left-style: solid; border-right-color: rgb(237, 237, 237); border-right-style: solid; border-top-color: rgb(237, 237, 237); border-top-style: solid; border-width: 1px 1px 0px; margin: 0px; padding: 4px 8px; vertical-align: baseline;">Pin 16 (LED-)</td></tr>
</tbody></table>
After setting up the hardware I was ready for the coding part, it involved the following steps:<div>
<br /></div>
<div>
<ol>
<li>Download and install Arduino IDE from <a href="https://www.arduino.cc/en/Main/Software">https://www.arduino.cc/en/Main/Software</a></li>
<li>Download and decompres libraries Adafruit_ST7735 and Adafruit_GFX from <a href="https://learn.adafruit.com/adafruit-gfx-graphics-library/overview">https://learn.adafruit.com/adafruit-gfx-graphics-library/overview</a></li>
<li>Restart Arduino IDE and you are ready!</li>
</ol>
<div>
The only diference regarding code posted by Adafruit is the pin initialization:</div>
<div>
<br /></div>
<div>
<div>
#define TFT_PIN_CS 10 // Arduino-Pin an Display CS </div>
<div>
#define TFT_PIN_DC 9 // Arduino-Pin an </div>
<div>
#define TFT_PIN_RST 8 // Arduino Reset-Pin</div>
</div>
<div>
<div>
<br /></div>
<div>
#include <SPI.h></div>
<div>
#include <Adafruit_GFX.h> </div>
<div>
#include <Adafruit_ST7735.h> </div>
</div>
<div>
<br /></div>
<div>
After this small change you are ready to use the TFT, as a proof of concept I made a simple game to just travel around a mace gathering some kind of diamonds:<br /><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwS0rOFyUdzz2dIWhT7RQHWaALz6c73oZcLClDkQkp_d7wc4liDGj4NX6qitHFG683SfSmvDlDUm1DBWwaYCpCM3lQzvIE-vPJvJZ4ox21RLtajLQpoxPS5NQ3uAWMWr_ciq8jOwm7Rszi/s1600/level1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiwS0rOFyUdzz2dIWhT7RQHWaALz6c73oZcLClDkQkp_d7wc4liDGj4NX6qitHFG683SfSmvDlDUm1DBWwaYCpCM3lQzvIE-vPJvJZ4ox21RLtajLQpoxPS5NQ3uAWMWr_ciq8jOwm7Rszi/s320/level1.png" width="256" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdEV0YgcvAEZJdrXAKIcawmCtnzn28lMIagYFc-DeeUx2kGZcTY_fynJPjgTe1FCpY0mZmmEeqqO_ZURzCrjg-5VtIsBCU6bX5XjWtw7INj40WU1wOi4MiarOkJ8G3bEM97RTdcnftW6yo/s1600/level2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhdEV0YgcvAEZJdrXAKIcawmCtnzn28lMIagYFc-DeeUx2kGZcTY_fynJPjgTe1FCpY0mZmmEeqqO_ZURzCrjg-5VtIsBCU6bX5XjWtw7INj40WU1wOi4MiarOkJ8G3bEM97RTdcnftW6yo/s320/level2.png" width="248" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiokkd1Spr6mri6hayXIqB5vPDvqoaM4nSUGbaSrY3uTmDP3knZvlBRrgwprbKvM6_kOAe_iB-MqXeHVRYZcqInpW0_-GErsFo3JBQeXZ1u4vztK8GgH1lfwXCVjc62laA-B2o8rk7pbWoo/s1600/level3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiokkd1Spr6mri6hayXIqB5vPDvqoaM4nSUGbaSrY3uTmDP3knZvlBRrgwprbKvM6_kOAe_iB-MqXeHVRYZcqInpW0_-GErsFo3JBQeXZ1u4vztK8GgH1lfwXCVjc62laA-B2o8rk7pbWoo/s320/level3.png" width="256" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
Red point is the player, and green point is exit of the level, I am actually happy as it was very simple to set up everything and Arduino code is basically C/C++ (my old friend), so I just need to define some variables:<br />
<br />
<i><span style="color: blue;">Adafruit_ST7735 screen = Adafruit_ST7735(screen_PIN_CS, screen_PIN_DC, screen_PIN_RST); </span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">int sensorY = A0; //Analog pin Y ->A0</span></i><br />
<i><span style="color: blue;">int sensorX = A1; //Analog pin X ->A1</span></i><br />
<i><span style="color: blue;">int sensorValueY = 0;//Value for Y analog pin</span></i><br />
<i><span style="color: blue;">int sensorValueX = 0;//Value for X analog pin</span></i><br />
<i><span style="color: blue;">int myx =1;//X location of the player</span></i><br />
<i><span style="color: blue;">int myy =1;//Y location of the player</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">int tx=0;//Used to convert joystick X analog input into +-1</span></i><br />
<i><span style="color: blue;">int ty=0;//Used to convert joystick Y analog input into +-1</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">int x=0;//temp variables for loops</span></i><br />
<i><span style="color: blue;">int y=0;//temp variables for loops</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">int tilesize = 10;//Size of the tiles(in pixels)</span></i><br />
<i><span style="color: blue;">int mymap[20][20];//Game map</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">int points =0;//Points..</span></i><br />
<i><span style="color: blue;">int level =1;//Level..</span></i><br />
<br />
Then some functions to draw the map and load levels map:<br />
<i><span style="color: blue;">void DrawMap(){//Draw array on the screen</span></i><br />
<i><span style="color: blue;">screen.fillScreen(ST7735_BLACK);</span></i><br />
<i><span style="color: blue;">for (x=0;x<14;x++){</span></i><br />
<i><span style="color: blue;"> for (y=0;y<14;y++){</span></i><br />
<i><span style="color: blue;"> if( mymap[x][y]==1){screen.fillRoundRect(x*tilesize+1,y*tilesize+1,9,9,3,ST7735_CYAN);}//Wall</span></i><br />
<i><span style="color: blue;"> if( mymap[x][y]==2){screen.fillRoundRect(x*tilesize+3,y*tilesize+3,5,5,3,ST7735_WHITE);}//Diamond</span></i><br />
<i><span style="color: blue;"> if( mymap[x][y]==9){screen.fillRoundRect(x*tilesize+1,y*tilesize+1,9,9,3,ST7735_GREEN);}//End of level</span></i><br />
<i><span style="color: blue;"> }</span></i><br />
<i><span style="color: blue;"> } </span></i><br />
<i><span style="color: blue;">}</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">void LoadLevel1(){//Init level array</span></i><br />
<i><span style="color: blue;">for (x=0;x<20;x++){</span></i><br />
<i><span style="color: blue;"> for (y=0;y<20;y++){</span></i><br />
<i><span style="color: blue;"> mymap[x][y]=2;</span></i><br />
<i><span style="color: blue;"> }</span></i><br />
<i><span style="color: blue;">}</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">for (x=0;x<13;x++){</span></i><br />
<i><span style="color: blue;"> mymap[x][0]=1;</span></i><br />
<i><span style="color: blue;"> mymap[x][13]=1;</span></i><br />
<i><span style="color: blue;">}</span></i><br />
<i><span style="color: blue;">for (x=0;x<14;x++){</span></i><br />
<i><span style="color: blue;"> mymap[0][x]=1;</span></i><br />
<i><span style="color: blue;"> mymap[12][x]=1;</span></i><br />
<i><span style="color: blue;">}</span></i><br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
I think it is easy to imagine LoadLevel2 and LoadLevel3 how do they work ;), next step is to perform initialization function from Arduino:<br />
<br />
<i><span style="color: blue;">void setup(void) {//Arduino init function</span></i><br />
<i><span style="color: blue;">screen.initR(INITR_BLACKTAB); //Init TFT</span></i><br />
<i><span style="color: blue;">LoadLevel1();//Load level 1</span></i><br />
<i><span style="color: blue;">DrawMap();//Draw Map</span></i><br />
<i><span style="color: blue;">screen.setTextSize(1);</span></i><br />
<i><span style="color: blue;">screen.setTextWrap(true); </span></i><br />
<i><span style="color: blue;">screen.setTextColor(ST7735_WHITE);</span></i><br />
<i><span style="color: blue;">screen.setCursor(1,140);</span></i><br />
<i><span style="color: blue;">screen.print("Points:");//Draw starting points</span></i><br />
<i><span style="color: blue;">screen.setCursor(50,140);</span></i><br />
<i><span style="color: blue;">screen.print(points);</span></i><br />
<i><span style="color: blue;">screen.setCursor(1,150);</span></i><br />
<i><span style="color: blue;">screen.print("Level:");//Draw starting level</span></i><br />
<i><span style="color: blue;">screen.setCursor(50,150);</span></i><br />
<i><span style="color: blue;">screen.print(level);</span></i><br />
<i><span style="color: blue;">}//End of setup</span></i><br />
<br />
Not much to say here, finally there is the game loop:<br />
<i><span style="color: blue;">void loop() {//Game loop (Arduino loop)</span></i><br />
<i><span style="color: blue;">tx=0;</span></i><br />
<i><span style="color: blue;">ty=0;</span></i><br />
<i><span style="color: blue;">sensorValueY = analogRead(sensorY);//Read joystick analog Y</span></i><br />
<i><span style="color: blue;">sensorValueX = analogRead(sensorX);//Read joystick analog D</span></i><br />
<i><span style="color: blue;">screen.fillRoundRect(myx*tilesize+1,myy*tilesize+1,9,9,3,ST7735_BLACK);//Replace current player location with a black box</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">//Convert analog values to +1 .. -1</span></i><br />
<i><span style="color: blue;">if (sensorValueY>600){ ty=1;}</span></i><br />
<i><span style="color: blue;">if (sensorValueY<400){ ty=-1;}</span></i><br />
<i><span style="color: blue;">if (sensorValueX>600){ tx=1;}</span></i><br />
<i><span style="color: blue;">if (sensorValueX<400){ tx=-1;}</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">if( mymap[myx+tx][myy+ty]!=1){//is it a wall?</span></i><br />
<i><span style="color: blue;"> //No: update player location</span></i><br />
<i><span style="color: blue;"> myx+=tx;</span></i><br />
<i><span style="color: blue;"> myy+=ty;</span></i><br />
<i><span style="color: blue;">}</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">if( mymap[myx][myy]==2){//is it a coin?</span></i><br />
<i><span style="color: blue;"> points++;</span></i><br />
<i><span style="color: blue;"> mymap[myx][myy]=0;//Update map </span></i><br />
<i><span style="color: blue;"> screen.fillRect(1,140,140,10,ST7735_BLACK);</span></i><br />
<i><span style="color: blue;"> screen.setCursor(1,140);</span></i><br />
<i><span style="color: blue;"> screen.print("Points:");//Update points counter</span></i><br />
<i><span style="color: blue;"> screen.setCursor(50,140);</span></i><br />
<i><span style="color: blue;"> screen.print(points);</span></i><br />
<i><span style="color: blue;"> }</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">if( mymap[myx][myy]==9){//is it end of level?</span></i><br />
<i><span style="color: blue;"> level++;</span></i><br />
<i><span style="color: blue;"> //If we change level we load new level</span></i><br />
<i><span style="color: blue;"> if (level == 1)LoadLevel1();</span></i><br />
<i><span style="color: blue;"> if (level == 2)LoadLevel2();</span></i><br />
<i><span style="color: blue;"> if (level == 3)LoadLevel3();</span></i><br />
<i><span style="color: blue;"> if (level == 4)level=1;//Back to first level</span></i><br />
<i><span style="color: blue;"> DrawMap();//Draw map again</span></i><br />
<i><span style="color: blue;"> screen.setCursor(1,140);</span></i><br />
<i><span style="color: blue;"> screen.print("Points:");</span></i><br />
<i><span style="color: blue;"> screen.setCursor(50,140);</span></i><br />
<i><span style="color: blue;"> screen.print(points);</span></i><br />
<i><span style="color: blue;"> screen.setCursor(1,150);</span></i><br />
<i><span style="color: blue;"> screen.print("Level:");</span></i><br />
<i><span style="color: blue;"> screen.setCursor(50,150);</span></i><br />
<i><span style="color: blue;"> screen.print(level); </span></i><br />
<i><span style="color: blue;">}</span></i><br />
<i><span style="color: blue;"><br /></span></i>
<i><span style="color: blue;">screen.fillRoundRect(myx*</span></i><span style="color: blue;"><i>tilesize</i></span><i><span style="color: blue;">+1,myy*</span></i><span style="color: blue;"><i>tilesize</i></span><i><span style="color: blue;">+1,9,9,3,ST7735_RED);//Draw player</span></i><br />
<i><span style="color: blue;">delay(100); //Delay to adjust game speed</span></i><br />
<i><span style="color: blue;">}//End of loop</span></i><br />
<i><span style="color: blue;"><br /></span></i>
Compared with other coding projects I have made I feel shame of this crap coding, but it actually works, it is not very complicated to think in replacing the colored squares with a real tileset, and make some real game clones like Tetris , Asteroids, Mario bross, etc.<br />
<br />
More content to come!<br />
<br />
<br />
<br /></div>
</div>
Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-3116888426138526842013-05-15T21:14:00.001+02:002013-05-15T21:14:51.511+02:00OpenGL 2.1 +.OBJ files<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0DehTfDhM4z5FO7JryTyrMQSl4ZNO1JntuMNS94ivTOvbX8T5GiBvAlGhkbMzwrybsSPvJbkss5e0gWshoFjpMd7df_itY4lncZdS38ZyHXzEaF_3aXBSI_AHXtoi7pLkSYdOzNoE2fEY/s1600/myland.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0DehTfDhM4z5FO7JryTyrMQSl4ZNO1JntuMNS94ivTOvbX8T5GiBvAlGhkbMzwrybsSPvJbkss5e0gWshoFjpMd7df_itY4lncZdS38ZyHXzEaF_3aXBSI_AHXtoi7pLkSYdOzNoE2fEY/s400/myland.png" width="400" /></a></div>
<My land ahead> <br />
<br />
<br />
I have been out of business for a long time, too long in fact, but I gathered all my strength and decided I still wont surrender , so I decided to take a few steps to continue with my project.<br />
<br />
First thing I thought was I needed to improve my Opengl Skills, that involved:<br />
<ul>
<li>Drooping my Opengl1.x skills ( forgetting all the immediate drawing stuff)</li>
<li>Start with at least Opengl 2.1 (vertex and fragment shaders, + working with VAOS)</li>
</ul>
<br />
<br />
I could have chosen Opengl 3.3 or even 4.3, but that would mean dropping support for a wide amount of persons including all the "vga integrated in the motherboard" + mac users, so Opengl 2.1 + shader model #120 was my target.<br />
<br />
I started learning on "modern opengl tutorial sites" like:<br />
<ul>
<li>http://www.opengl-tutorial.org/</li>
<li>http://ogldev.atspace.co.uk/index.html</li>
<li>http://arcsynthesis.org/gltut/</li>
</ul>
First dilemma I had was which API could I use with Opengl, I could have used SDL, but that would mean switching to SDL2, then I had Glut, not for me!! finally I chose "GLFW": http://www.glfw.org/ which is basically a framework to use opengl + window management + keyboard + mouse input, everything simple and working on Linux /Windows /Mac OS/X isn't it nice?<br />
<br />
So I went my way working on it until I had an idea about how to use basic functions, and made a simple class to load exported objects on "<span style="font-weight: normal;"><span dir="auto">Wavefront .obj</span></span>" format, the class is quite simple to use:<br />
<br />
<ul>
<li>cobj myasset; //instance an object..</li>
<li>myasset.loadmodel("land.obj","map.tga"); //load the obj file + the texture</li>
<li>myasset.draw(MVP); //draws the object!</li>
</ul>
I think it's hard to make it easier to use ;) the result of my work:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt59GhOv723uzys43-g8ONCTTWk_JfzKxoUsBg2vVziIRMGlTzKZVY9V_vpw_PtP0yljwgydV30SyNL_66w5gF-eoLbzuVQtt8E1WxZt6DvsYeld1UtBy6OssZZKuFfoBe0p55xSMEp9FA/s1600/two_models.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgt59GhOv723uzys43-g8ONCTTWk_JfzKxoUsBg2vVziIRMGlTzKZVY9V_vpw_PtP0yljwgydV30SyNL_66w5gF-eoLbzuVQtt8E1WxZt6DvsYeld1UtBy6OssZZKuFfoBe0p55xSMEp9FA/s320/two_models.png" width="320" /></a></div>
<Forgive me for the silly models!><br />
<br />
So I had an object loader, what now? I needed somewhere to place the models, that was my second dilemma: I have no artistic skill so how to make a map?...<br />
<br />
-libnoise (http://libnoise.sourceforge.net/) came to rescue me.. again, I just recovered an old project I used to generate noise maps and made an exporter so I could write obj files with the noise map, that is basically an height map + a color map, after a few attempts I got it working, and I was able to load it into blender!!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvC6N6C1FsFTREc6YfjOaAY892dg8qVz3mOGcuD0W0fktgbw12HGt-mKgwlrVpD1_zCMZHFelbs0jDbhfxaySPuQV3y5ppI2ELBI-5UrK3SQfPoe8t-3Q-7YbQgrHzLz2esRNB0tU3Pbcu/s1600/land.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhvC6N6C1FsFTREc6YfjOaAY892dg8qVz3mOGcuD0W0fktgbw12HGt-mKgwlrVpD1_zCMZHFelbs0jDbhfxaySPuQV3y5ppI2ELBI-5UrK3SQfPoe8t-3Q-7YbQgrHzLz2esRNB0tU3Pbcu/s400/land.png" width="400" /></a></div>
<br />
And, adding a model + a transparent sea texture I got the final result:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0DehTfDhM4z5FO7JryTyrMQSl4ZNO1JntuMNS94ivTOvbX8T5GiBvAlGhkbMzwrybsSPvJbkss5e0gWshoFjpMd7df_itY4lncZdS38ZyHXzEaF_3aXBSI_AHXtoi7pLkSYdOzNoE2fEY/s1600/myland.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0DehTfDhM4z5FO7JryTyrMQSl4ZNO1JntuMNS94ivTOvbX8T5GiBvAlGhkbMzwrybsSPvJbkss5e0gWshoFjpMd7df_itY4lncZdS38ZyHXzEaF_3aXBSI_AHXtoi7pLkSYdOzNoE2fEY/s400/myland.png" width="400" /> </a></div>
<div class="separator" style="clear: both; text-align: center;">
<back into the business again!> </div>
<br />
I'm exhausted, but at the same time very happy, good things coming soon! <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0DehTfDhM4z5FO7JryTyrMQSl4ZNO1JntuMNS94ivTOvbX8T5GiBvAlGhkbMzwrybsSPvJbkss5e0gWshoFjpMd7df_itY4lncZdS38ZyHXzEaF_3aXBSI_AHXtoi7pLkSYdOzNoE2fEY/s1600/myland.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"> </a> </div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-43292733829516036162012-11-15T23:03:00.001+01:002012-11-15T23:04:31.733+01:00New TilesetsI'm back, again!<br />
<br />
I have retaken my project after the MySql + OpenGL experiments<br />
<br />
My first step after deciding to improve the graphics of my game was to update my horrible tileset, so I searched for GPL'ed tilesets,... I was about to surrender but finally I found a very nice place: <a href="http://rltiles.sourceforge.net/">RL Tiles</a> , a nice collection of GPL tilesets that gave me basically all what I needed:<br />
<br />
<b>Monsters / characters (From Dungeon Crawl):</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh85pSRMwe9H1lZRq_fHESG2y0pMboPCqPtfVxsNPRPz8Jj_zvnGOZfDd3_zaUkR5r41yrejHPc9INDM7DkQL1YP7Kc_I9ZhlKFxaCGlLryDuiDPVLZPiYfU3IyW5FavAHqmmtOMP4oH9u/s1600/creatures_alpha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjh85pSRMwe9H1lZRq_fHESG2y0pMboPCqPtfVxsNPRPz8Jj_zvnGOZfDd3_zaUkR5r41yrejHPc9INDM7DkQL1YP7Kc_I9ZhlKFxaCGlLryDuiDPVLZPiYfU3IyW5FavAHqmmtOMP4oH9u/s320/creatures_alpha.png" width="320" /></a></div>
<br />
<br />
<b>Items </b><b><b>(From Dungeon Crawl)</b>:</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Hr1VHenE8IxVB3IBZxvQ46BNEvT6qxKeIlSrG8JCt0psNK6kBAHmJeWJOSqa6xczB03atFtcAACtrhWj-bnsxt8ZbzjNrbmJiBZSLJVRP_G-4g5OKzkaXXX1yFeGpRKgTvXrf6JGcz40/s1600/items_alpha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj6Hr1VHenE8IxVB3IBZxvQ46BNEvT6qxKeIlSrG8JCt0psNK6kBAHmJeWJOSqa6xczB03atFtcAACtrhWj-bnsxt8ZbzjNrbmJiBZSLJVRP_G-4g5OKzkaXXX1yFeGpRKgTvXrf6JGcz40/s320/items_alpha.png" width="320" /></a></div>
<br />
<br />
But at this point I needed some aid with the terrains + some magic effects, so I remembered a very fun, addictive rogue like made in Java: <a href="http://sourceforge.net/projects/tyrant/">Tyrant - The Java Roguelike</a> I asked the creator, Mike Anderson if I could include the game images and he accepted if I redistribute it under GPL license, Thanks Mike!!<br />
<br />
<b>Mixed terrain from Dungeon crawl / Tyrant:</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge4uTSLr8L9aqXqbtBcFHLi8C6LqdQ5Xbz-ohWiukZKyfv0J64aOYz2hEQtlPCpam6GJaSelzQ2CW1nv9YrMD-iWbCPWQiVSn8tEA8DTI8o5yodBbyfxrAE_ZE-bynic-lOpTcNO9kjIUp/s1600/terrain_alpha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEge4uTSLr8L9aqXqbtBcFHLi8C6LqdQ5Xbz-ohWiukZKyfv0J64aOYz2hEQtlPCpam6GJaSelzQ2CW1nv9YrMD-iWbCPWQiVSn8tEA8DTI8o5yodBbyfxrAE_ZE-bynic-lOpTcNO9kjIUp/s320/terrain_alpha.png" width="320" /></a></div>
<b>Magic Effects (Courtesy from Tyrant - the Java Roguelike):</b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4jKqoi0iOjir_cVC8miKeT4lJ2y2Ed6_Ua5P5_6ulYNs9uVHi41IGs1CYYEn052oevjmL3loS3jqEpOwFvMgVM3mAHU5_8LaXg4X_chAOkgPBzHOQYn9ixrgNWy-ONDfaEuAaxVm0Tevu/s1600/magic_alpha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi4jKqoi0iOjir_cVC8miKeT4lJ2y2Ed6_Ua5P5_6ulYNs9uVHi41IGs1CYYEn052oevjmL3loS3jqEpOwFvMgVM3mAHU5_8LaXg4X_chAOkgPBzHOQYn9ixrgNWy-ONDfaEuAaxVm0Tevu/s320/magic_alpha.png" width="320" /></a></div>
<br />
<br />
<br />
All tilesets are 1024*1024 size, with the transparency set to Red:255/Green:0/Blue:255 (Pink), each one is divided into 32* 32 tiles with a size of 32*32 pixels (1024 tiles / tileset, space to grow!), finally all them are free to redistribute / use under GPL license.<br />
<br />
In the next post I will speak about map storage with MySql and loading to ram..<br />
<br />
Bye Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-72699504243151232442012-11-12T23:14:00.001+01:002012-11-15T23:04:31.736+01:00Banned from 4Shared<Today I got a crazy e-mail from 4shared:><br />
<br />
<i>Dear Sir/Madam,<br /><br />We have received a notification that certain materials you posted on the 4Shared website as described below infringe upon someone else’s copyright:</i> <i><br /><br /><a href="http://www.4shared.com/zip/HeeXFWb7/rpg.htm" target="_blank">http://www.4shared.com/zip/<wbr></wbr>HeeXFWb7/rpg.htm</a></i> <br />
<br />
<I got really shocked... me infringing copyrights? what??? Then I went to my blog and I got into my download section : ><br />
<br />
<br />
<div class="separator" style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none; clear: both; text-align: center;">
<a href="http://www.blogger.com/" imageanchor="1" style="clear: right; cssfloat: right; float: right; margin-bottom: 1em; margin-left: 1em;"></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGll3tCgkFWofPqN9vYpyHKz0NRRVx6d5m8g6nSW2zhFYNuWvUOEban6nXlHmOaCSuISQ_ciM4b5idLXqm9SEhrfJt5vv_dgdmeloYNt4KlI7Pr-zM0iQ_XNgpJ6VevTJcf49V92W8PJy_/s1600/rpg.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" rea="true" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGll3tCgkFWofPqN9vYpyHKz0NRRVx6d5m8g6nSW2zhFYNuWvUOEban6nXlHmOaCSuISQ_ciM4b5idLXqm9SEhrfJt5vv_dgdmeloYNt4KlI7Pr-zM0iQ_XNgpJ6VevTJcf49V92W8PJy_/s320/rpg.png" width="309" /></a></div>
<div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;">
<br /></div>
<div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;">
</div>
<br />
<So a tutorial I have made coding with Open Source tools is infringing copyrights? libSDL? maybe Code::Blocks?><br />
<br />
<The e-mail continues:><br />
<br />
<div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;">
<i>Access to the material complained of has been temporarily disabled or such material has been removed. In addition, the public sharing function for your account has been disabled. For instructions on how to dispute the copyright infringement claim, please read the section titled Counter Notification Requirements below. For instructions on how to re-activate your sharing function, read the section titled Re-activation of the sharing function of your account at the end of this letter.<br /><br />In accordance with 4shared’s Copyright Policy, to which you are bound by virtue of agreeing to our Terms of Use, your account will be terminated and your access to 4shared services permanently banned following three instances of copyright infringement. <span style="color: #cc0000;">Unless you respond by counter notification and successfully dispute the copyright owner’s claim, this will be considered your FIRST instance of infringement under the three-strike policy</span>.</i> </div>
<br />
<So I have been accused by someone I don't know from something I have not done, and unless I demonstrate It's not right I may get permanently banned... strike one!!><br />
<br />
<i>Counter Notification Requirements<br />If you do not believe that such materials are infringing and wish to have access restored, please provide a counter notification containing the following information to 4Shared Designated Agent for Notice of Claims of Copyright Infringement (“Designated Agent”) as set forth below: <br />1) Identify the material that was removed or disabled, and the location where it appeared before it was removed or disabled;<br />2) Declare under penalty of perjury that you have a good faith belief that the material at issue was removed or disabled as a result of either mistake or misidentification of the material to be removed or disabled;<br />3) <span style="color: red;">Provide your name, address, and telephone number;</span><br />4) Provide a statement that you consent to the jurisdiction of the federal district court for the judicial district in which your address is located, or if your address is outside of the United States, for any judicial district in which 4Shared may be found, and that you will accept service of process from the person who provided the notification or an agent of such person.<br />5)<span style="color: red;"> Provide your physical or electronic signature.</span><br /><br />Such counter notification must be sent via e-mail to our Designated Agent at dmca_agent@4Shared.com. </i> <br />
<br />
<So if I want to avoid being banned I have to send my PERSONAL ADDRESS, PHONE and I HAVE TO SIGN??? is that a judgement? should I pay a lawyer???, the email continues...><br />
<br />
<i>Alternatively, you may send the counter notification to our Designated Agent using the contact information below:<br /><br />Name of Designated Agent: Ganka Hadjipetrova</i> <i><br />Address of Designated Agent: 745 Distel Dr., Ste. 110, Los Altos, CA 94022<br />Facsimile Number of Designated Agent: <a href="tel:%28650%29%20433-5471" target="_blank" value="+16504335471">(650) 433-5471</a><br />If we receive a proper counter notice, then we may replace or cease disabling access to the allegedly infringing materials in ten business days in accordance with the provisions of the <span style="color: red;">DMCA</span>, unless our Designated Agent first receives notice that an action has been filed by the complainant seeking a court order to restrain the account holder from engaging in infringing activity relating to the material on our system or network.</i><br />
<br />
<br />
<br />
<i>You should also note that if you make any material misrepresentation in your counter notification that the material or activity was removed or disabled by mistake or misidentification, you will be liable for all damages, including costs and attorneys’ fees, incurred by 4Shared or any copyright owner or copyright owner’s authorized licensee as the result of our relying upon such misrepresentation in replacing the removed material or ceasing to disable access to it.<br /><span style="color: red;">In the event you provide us with counter notification compliant with all requirements described above and the rights owner does not pursue the infringement claim further, 4shared will remove this instance of copyright infringement from your record and will not consider the take-down notice for purposes of the three-strike repeat infringer termination policy</span>. If we receive a compliant counter notification, we will also re-activate your account’s sharing capability. Note that regardless of whether or not you challenge the infringement claim via a counter notification, 4shared will keep the take-down notification for its records.</i><br />
<br />
<So resuming FIRST: Take down my content with no real facts that it's something illegal , THEN if you dare give all your personal data to someone you don't know you may get your content restored... It stinks!! ><br />
<br />
<i>Re-Activation of the Sharing Function of Your Account<br />Note that if you send us a counter notification fulfilling all requirements described above, your account’s sharing functionality will be re-activated.<br />In case you do not challenge the take-down notification, you may still be able to re-activate the sharing function of your account. To do that, you must remove all copyrighted content for which you do not hold author’s rights and do not otherwise have authorization to use. Once you have removed all unauthorized materials from your account, you must declare under penalty of perjury that your account does not contain infringing files <a href="http://www.4shared.com/confirmRemoval.jsp?li=JFIPJJJZJDIMIZJAJFJAIXIMIMJZKUKUJQJRIUIRJOJKIYIPKQIOJQKBJRKTJXKLKLKNJKJAIRJJISIR" target="_blank">here</a>. Take note that you will still have access to your files if you do not verify your account is infringement free, but you will not be able to share them publicly.</i><br />
<br />
<i> Thank you. <br />Sincerely, <br />4shared Support Team<br /><a href="mailto:support@4shared.com" target="_blank">support@4shared.com</a></i><br />
<br />
<At this moment I was thinking.... OK I'm pretty sure that is just an scammer, but when I got into my 4shared account and found my file has been removed I got really angry!!!!><br />
<br />
< Guess what? I wont reply, I wont stay in a place I can get blamed for anybody with no , I will let the account die and will never return here><br />
<br />
< +1 to Digital Millennium Copyright Act, they have stopped an indie developer from sharing his Open Source - projects at 4shared!! Must feel real pride..><br />
<br />
<Sweet Internet Freedom> <br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com3tag:blogger.com,1999:blog-1792734122980275490.post-53308636129453099172012-10-04T23:34:00.002+02:002012-11-15T23:04:31.735+01:00libNoise, OpenGL and George R.R. MartinHello<br />
<br />
I've been quite busy in the last weeks, but still had time to investigate a pair of libs:<br />
<br />
When I was thinking in how to make a procedural generated map I saw <a href="http://simblob.blogspot.com.es/2010/01/simple-map-generation.html">simple-map-generation</a> from Amit Pattel, so I knew I had to use a noise function generator, that lead me to discovered <a href="http://libnoise.sourceforge.net/">libnoise</a>: it is a simple library that allows to generate noise maps, apply colors , generate height maps, and many other things!!:<br />
<br />
<div style="text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDtfCuCKwqe3fF2MaGJ1VvTQMZ7ae5KBymHvSc9wJN5LX4g1dlbto3wnbSUsrNo3D5EK2CtqPe-c3ecpfm9fRgcEvRNGJ87kDomk78scHgTCtvOTxP4E38f5_0EmBJEPNgUZsAprab8EgI/s1600/screenshot-c.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="251" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDtfCuCKwqe3fF2MaGJ1VvTQMZ7ae5KBymHvSc9wJN5LX4g1dlbto3wnbSUsrNo3D5EK2CtqPe-c3ecpfm9fRgcEvRNGJ87kDomk78scHgTCtvOTxP4E38f5_0EmBJEPNgUZsAprab8EgI/s320/screenshot-c.png" width="320" /> </a></div>
<div style="text-align: center;">
<2d noise map loaded (left), and a zoomed window (right) ></div>
<br />
After playing a while with it I knew my maps would be generated by 2D noise functions , first I loaded the map with standard SDL, and made a map explorer, with the zoomed map..<br />
<br />
Then I tought.. what if those colored quads were drawn by OpenGL???<br />
<br />
I was kinda afraid and excited about the idea at the same time...<br />
<br />
Excited about all the things I could do with OpenGL...<br />
<br />
Afraid because OpenGL meant start from 0 again .... So I got all the courage I had and told me myself... "If you are into computers you will be learning all your life"<br />
<br />
So I started to read the "OpenGL RedBook" and after like 250 pages and failing a few times I finally got my color-map to load on screen with Opengl!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBmRPNihR5jOkGM11Jjf7cjBKX1PRMKVS5mDDizC9He597wBrsYFto08ibZc4YHAlGlqSintjk1hmzNX9jsACAlVduPSeGW3kZWOH7_3eb3gfJN_CcBa87ZyNusVpmztoLrT5t87PQIUJm/s1600/Screenshot-a.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBmRPNihR5jOkGM11Jjf7cjBKX1PRMKVS5mDDizC9He597wBrsYFto08ibZc4YHAlGlqSintjk1hmzNX9jsACAlVduPSeGW3kZWOH7_3eb3gfJN_CcBa87ZyNusVpmztoLrT5t87PQIUJm/s320/Screenshot-a.png" width="320" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm30KSWnwSe1-uJiZGhnA871h7kgDQRjm_W1MnVC6R1pWODoutiLp3jD1sfzkQtTp7B25XgcdwR5ggSnE-lQnv8bb2rXzG4C5m0-L5Y1-6-35Vdwz6sbtWFwiGVJSCMGAg6V96efjanrsO/s1600/Screenshot-b.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="256" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgm30KSWnwSe1-uJiZGhnA871h7kgDQRjm_W1MnVC6R1pWODoutiLp3jD1sfzkQtTp7B25XgcdwR5ggSnE-lQnv8bb2rXzG4C5m0-L5Y1-6-35Vdwz6sbtWFwiGVJSCMGAg6V96efjanrsO/s320/Screenshot-b.png" width="320" /></a></div>
<br />
Well, it was just a bunch of quads, but you could just Imagine it is a map...<br />
<br />
After that I loaded the height map too and made the "z" from the map depend in the height, so I got the first improvements:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiViu0COwDHVc8Py6_zoQAFKXRTeUy-cWOLG83HK-AkeRmpdcYIsxTwJe7jqqnFSh6RErkevKybqa-MOsSCNt1g7A-Szf2U7LjckFvVW-J_hukR0J6hCM1xwfOVCaLjnAeYGm5T5SE7zZ8L/s1600/Screenshot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiViu0COwDHVc8Py6_zoQAFKXRTeUy-cWOLG83HK-AkeRmpdcYIsxTwJe7jqqnFSh6RErkevKybqa-MOsSCNt1g7A-Szf2U7LjckFvVW-J_hukR0J6hCM1xwfOVCaLjnAeYGm5T5SE7zZ8L/s320/Screenshot.png" width="301" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK96S-lSn7_Kk0DjepvEMUoKG4fmBzyu_lAnCgUakINmVX71DibRTW7yd-l_2JW8ScHLN_bqcYDH1p0c9OKytp3YhggW0nqfdVb7IQ50_STBF6GEg6w-yHfl1Z6sBe-KD_M23SXf2Vew6P/s1600/Screenshot-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjK96S-lSn7_Kk0DjepvEMUoKG4fmBzyu_lAnCgUakINmVX71DibRTW7yd-l_2JW8ScHLN_bqcYDH1p0c9OKytp3YhggW0nqfdVb7IQ50_STBF6GEg6w-yHfl1Z6sBe-KD_M23SXf2Vew6P/s320/Screenshot-1.png" width="303" /></a></div>
<br />
But I didn't wanted to make a minecraft-clone... so I decided to make the quads based in the corners, not just floating quads...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOhtEmdc1j_k5BHraAR9gqrb7om4bm_5jUE4B6XAOTl168QPPq-wCVK_AbYUITDtKDQybOZTv2FVxCQ6E1N8VF7-Akp4pQtPijoNgSqs4ut_xkMOzMyLuter1wMkVd1515AsaJ12G-O0Iu/s1600/Screenshot-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhOhtEmdc1j_k5BHraAR9gqrb7om4bm_5jUE4B6XAOTl168QPPq-wCVK_AbYUITDtKDQybOZTv2FVxCQ6E1N8VF7-Akp4pQtPijoNgSqs4ut_xkMOzMyLuter1wMkVd1515AsaJ12G-O0Iu/s320/Screenshot-3.png" width="301" /></a></div>
<br />
<br />
<br />
<br />
<br />
I failed in my first attempt, but had a very fun land strips...<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidctKSAOWYzIk6v3CDcVFdvrPAiDfumWs5S3Yltlp7bAgz9BbxaNwl_9C0DwG-po2Mol07HpFR6L6n9Lbu15LakTp0JW-CaxLcxyCALRo5gU9mlefxXqygWTI-kBPiV5Nccg9w2rQMbekX/s1600/screenshot-4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidctKSAOWYzIk6v3CDcVFdvrPAiDfumWs5S3Yltlp7bAgz9BbxaNwl_9C0DwG-po2Mol07HpFR6L6n9Lbu15LakTp0JW-CaxLcxyCALRo5gU9mlefxXqygWTI-kBPiV5Nccg9w2rQMbekX/s320/screenshot-4.png" width="307" /></a></div>
<br />
<br />
But finally made it! I was starting to get very satisfied with the results, but I wanted to make it smooth so I divided the quads into triangles:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxaG_LIDtxlwklxYRJXFiv4jyWV18pVg2aKdRZMkAcZ_0QlcQAlldzsgQc57wmZqtdsHzHCPgkKh_QCP8O0TGsH62tOkpTbM6Wj_MkBm1awohIL0WO_-6zutgFcqTBX8MTZDBxE-IrVgJg/s1600/screenshot5.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxaG_LIDtxlwklxYRJXFiv4jyWV18pVg2aKdRZMkAcZ_0QlcQAlldzsgQc57wmZqtdsHzHCPgkKh_QCP8O0TGsH62tOkpTbM6Wj_MkBm1awohIL0WO_-6zutgFcqTBX8MTZDBxE-IrVgJg/s320/screenshot5.png" width="320" /></a></div>
<br />
It looked much better, but after I applied normals to all vertexes I got the look I was looking for:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmxf-xKlkwxzixHUhvvl0NvW0vtlNaF-C56GfxYs5nyb0SBzRwTvgmNNBNQx6CbEH2M8kpfPHn0R5m8xj7zfN9tBRk_ioX20JKXQLwqs1yVAYph7Ojh1KPrxRcGoq_t3XU-5Y6X6_CuMKk/s1600/normals_ok.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhmxf-xKlkwxzixHUhvvl0NvW0vtlNaF-C56GfxYs5nyb0SBzRwTvgmNNBNQx6CbEH2M8kpfPHn0R5m8xj7zfN9tBRk_ioX20JKXQLwqs1yVAYph7Ojh1KPrxRcGoq_t3XU-5Y6X6_CuMKk/s320/normals_ok.png" width="305" /></a></div>
<br />
<br />
<br />
<br />
<br />
Got it, finally!! , so resuming:<br />
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgULjp-RBn73aSrZv-7Zmy1kw3itJWgMYJh1jHnc8_bSgF60fn_pAC9kLMKb3MtsbPJwNBNMhKt9DmVdRssSDf8GwQOaOgDDmD1aMNCQJjb-Z20b1AvyP2IBbwRwjDv9TyQMLJuYkjxy9zF/s1600/map.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgULjp-RBn73aSrZv-7Zmy1kw3itJWgMYJh1jHnc8_bSgF60fn_pAC9kLMKb3MtsbPJwNBNMhKt9DmVdRssSDf8GwQOaOgDDmD1aMNCQJjb-Z20b1AvyP2IBbwRwjDv9TyQMLJuYkjxy9zF/s320/map.png" width="320" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="text-align: center;">
<A Map></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
+</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDrZgJE5bBU3epnQKvSMFMxH9cLhUA3R3ZZGI4SloB52MrQeyADklflnE9PSrLyh0tpELSXQpkA0vhQ8-BHsonGbTC_8XNrWTvlyABrCbImC5gf93ZKhfbXfXS1OoYdfQIQBtwfoyuFid1/s1600/mapheight.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDrZgJE5bBU3epnQKvSMFMxH9cLhUA3R3ZZGI4SloB52MrQeyADklflnE9PSrLyh0tpELSXQpkA0vhQ8-BHsonGbTC_8XNrWTvlyABrCbImC5gf93ZKhfbXfXS1OoYdfQIQBtwfoyuFid1/s320/mapheight.png" width="320" /></a></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
<An height map></div>
<div style="text-align: center;">
<br /></div>
<div style="text-align: center;">
=</div>
<div style="text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2i0GJL_NgT_hUNegG76JcM_xK6Wj5sZRxd5bmoAwW7NXsGgxaqtjSUIDFMmFITg5BGQnxhg4wtEL6rwFo9RmUjoZQt8PjJuR8TA3ni1n5nOFC8op4zfBrp2_I-WzQ_5E3HPHGMKoa62Zo/s1600/map3d.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2i0GJL_NgT_hUNegG76JcM_xK6Wj5sZRxd5bmoAwW7NXsGgxaqtjSUIDFMmFITg5BGQnxhg4wtEL6rwFo9RmUjoZQt8PjJuR8TA3ni1n5nOFC8op4zfBrp2_I-WzQ_5E3HPHGMKoa62Zo/s320/map3d.png" width="317" /></a></div>
<div style="text-align: center;">
<A 3D map!></div>
<br />
A final Note: had a few hard weeks at work so many days I just didn't had energy to code, I have been reading instead George R.R.Martin book "A song of Ice and fire", and got pretty hooked to it, in fact I read the 3rd book (+-900 pages) in a week...<br />
<br />
I'm still were do I continue now, any suggestions?<br />
<br />
See you<br />
Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com1tag:blogger.com,1999:blog-1792734122980275490.post-7973697194129991932012-08-20T14:04:00.001+02:002012-08-20T14:04:28.544+02:00Handle user accounts with MySqlHello<br />
<br />
Now we have a solid way to store and request data the next step is going to be the creation of user accounts.<br />
<br />
First we are going to prepare the database, to do so we will connect to the mysql server:<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>mysql -h localhost -u root -p</pre>
</div>
<br />
Create a database<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>crete database rpgdata;</pre>
</div>
<br />
Use the newly created database<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>use rpgdata;</pre>
</div>
<br />
Then create a table, that will store the user accounts<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> CREATE TABLE accounts (</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> id INT AUTO_INCREMENT,</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> fullname VARCHAR(60),</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> email VARCHAR(120),</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> password VARCHAR(30),</span> </pre>
<pre> <span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> lastlogin TIMESTAMP,</span></pre>
<pre><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> PRIMARY KEY (id));</span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span></pre>
</div>
<br />
<br />
We want to login into the game with an existent account or to create a new one, after that step we will get into game character creation (the next step), to simplify things I'm gonna make a text-only client , and a simplified server too.<br />
<br />
The logic will be:<br />
<ol>
<li>Client connect to the server socket</li>
<li>Client displays two options:2a-create a new character, 2b-login with an existing character</li>
<li>If we choose to create a new character the client will show list of text fields we need to fill to create the account</li>
<li>If we choose to login with an existing account we will fill our username (email) and password. </li>
</ol>
In the first case, it asks for: <br />
<ol></ol>
<ul>
<li>Full user name</li>
<li>email(we will use it like our user account)</li>
<li>password</li>
<li>password (another time), to prevent mistakes when typing</li>
</ul>
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> cout << "NEW ACCOUNT CREATION" << endl;
cout << "Full name?: ";
cin >> fullname;
cout << "e-mail?: ";
cin >> username;
cout << "Password?: ";
cin >> password;
cout << "Repeat Password?: ";
cin >> password2;
if(password.compare(password2)==0)
{
done=true;
}else{
cout << "Passwords don't match" << endl;
}</pre>
</div>
<br />
After filling all the data, it will pack it and sent it to the server<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>std::stringstream Msg;</pre>
<pre>Msg << fullname << "#"<< username << "#" << password << "#";</pre>
<pre>NET.SockSend(CREATE_NEW_ACCOUNT,Msg.str().c_str());</pre>
</div>
<br />
After we receive the message in the server we are going to unpack the data and get the email.<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>switch (command){
case CREATE_NEW_ACCOUNT:
cout << "New account request" << endl;
data2.clear();
split(data[3],'#',data2);//I split it into strings
fullname = data2[0];
username = data2[1];
password = data2[2];
cout << "Fullname " << fullname << endl;
cout << "Username " << username << endl;
cout << "Password " << password << endl;</pre>
</div>
<br />
We will make a query to the MySql server with that email account<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> aquery.clear();
aquery = "select * from accounts where email = '";
aquery+= username;
aquery += "'";
cout << aquery << endl;
aSQL.executequery(aquery.c_str());//executing select query</pre>
</div>
<br />
<br />
If there is already an account with the same email we will reject the data and send a "duplicate account" message to the client, if we don't find it, then we save a new account to the server and send a "account created properly" message to the client<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> if (aSQL.getrow())
{
//Username duplicate..
cout << "Duplicate username.." << endl;
aNET.Clients[atoi(data[0].c_str())]->SockSend(DUPLICATE_ACCOUNT,"");
}else{
//We have not found username, ok to insert..
cout << "We have not found username, ok to insert.." << endl;
aquery.clear();
aquery = "insert into accounts values (NULL,'";
aquery+= fullname;
aquery+="' , '";
aquery+= username;
aquery+="' , '";
aquery+= password;
aquery+="', NULL)";
cout << aquery << endl;
aSQL.executequery(aquery.c_str());//executing select query
cout << "New user inserted" << endl;
aNET.Clients[atoi(data[0].c_str())]->SockSend(NEW_ACCOUNT_ACCEPTED,"");
}
break;</pre>
</div>
<br />
After we create a new user, it will return to the main menu.<br />
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span></pre>
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">In the second case, it asks for:</span></pre>
<ul>
<li>email</li>
<li>password</li>
</ul>
<br />
After filling the data, it will pack and sent it to the server<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> cout << "ACCOUNT LOGIN" << endl;
cout << "e-mail?: ";
cin >> username;
cout << "Password?: ";
cin >> password;
std::stringstream Msg;
Msg << username << "#" << password << "#";
NET.SockSend(LOGIN_WITH_ACCOUNT,Msg.str().c_str());</pre>
</div>
<br />
After we receive the message in the server we are going to unpack the data and get the email.<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> case LOGIN_WITH_ACCOUNT:
cout << "Login request" << endl;
data2.clear();
split(data[3],'#',data2);//I split it into strings
username = data2[0];
password = data2[1];
cout << "Username " << username << endl;
cout << "Password " << password << endl;</pre>
</div>
<br />
With the email we are going to make a query to the server asking for accounts with that email.<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> aquery.clear();
aquery = "select * from accounts where email = '";
aquery+= username;
aquery += "'";
cout << aquery << endl;
aSQL.executequery(aquery.c_str());//executing select query</pre>
</div>
<br />
If we receive no accounts, obviously, there is no such account.<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre> if (aSQL.getrow())
{</pre>
<pre> /... </pre>
<pre> }else{
//We have not found username..
cout << "Username not found.." << endl;
aNET.Clients[atoi(data[0].c_str())]->SockSend(UNKNOW_USERNAME,"");
}</pre>
</div>
<br />
If we have found that account we check the password match the one the user has typed.<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>//Username found
cout << aSQL.row[0] << " " << aSQL.row[1] << " " << aSQL.row[2] << " " << aSQL.row[3] << " " << aSQL.row[4] << endl;
std::string pass;
pass = aSQL.row[3];
if (pass.compare(password)==0)
{
cout << "Username/password match, login ok" << endl;
aNET.Clients[atoi(data[0].c_str())]->SockSend(ACCOUNT_ACCEPTED,"");
aNET.Clients[atoi(data[0].c_str())]->Login = true;
}else{
//wrong password
cout << "Password mismatch.. " << endl;
aNET.Clients[atoi(data[0].c_str())]->SockSend(BAD_PASSWORD,"");
}</pre>
</div>
<br />
If the password is right, it will send an ACCOUNT_ACCEPTED message.<br />
<br />
In the client side, after sending data to creating a new account or login with an existing account we will wait to the server to send us a reply<br />
<div id="code" style="background-color: #aaaaff; border-bottom: rgb(17,17,17) 1px; border-left: rgb(17,17,17) 1px; border-right: rgb(17,17,17) 1px; border-top: rgb(17,17,17) 1px; color: #333333;">
<pre>switch(command)
{
case ACCOUNT_ACCEPTED:
cout << "ACCOUNT_ACCEPTED" << endl;
reply = true;
logedin = true;
break;
case NEW_ACCOUNT_ACCEPTED:
cout << "NEW_ACCOUNT_ACCEPTED" << endl;
reply = true;
break;
case DUPLICATE_ACCOUNT :
cout << "DUPLICATE_ACCOUNT " << endl;
reply = true;
break;
case UNKNOW_USERNAME:
cout << "UNKNOW_USERNAME" << endl;
reply=true;
break;
case BAD_PASSWORD:
cout << "BAD_PASSWORD" << endl;
reply=true;
break;
}//switch</pre>
</div>
<br />
And basically that's all, We have now authenticated users, ready for the next step: Player creation process!<br />
<br />
<strong>Notes:</strong><br />
<ol>
<li><strong>Don't look for encryption</strong>: it is not yet implemented so the server / client are not secure, the reason for that is 1-Simplicity 2-Easier to understand incoming / outgoing packets and 3-It is very easy to add encryption later.</li>
<li><strong>Messages are not encoded:</strong> no binary numbers, just plain text, the reason the same in point 1.1 and 1.2 : making things simpler to understand.</li>
</ol>
The full code can be downloaded at <a href="https://code.google.com/p/jbfprj/downloads/list">https://code.google.com/p/jbfprj/downloads/list</a> or at the <a href="http://www.blogger.com/svn%20checkout%20http://jbfprj.googlecode.com/svn/trunk%20jbfprj-read-only">svn</a><br />
<br />
See you!Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-74420896597019684452012-08-07T23:17:00.003+02:002012-08-07T23:17:44.513+02:00A server socket classHello <br />
<br />
I'm going to describe a new class, (last one before I start with the server)<br />
<br />
We already have a class to store persistent data, now we need a way to communicate with the world. <br />
<br />
I need a class to start a TCP socket server then accept incoming TCP connections , I need to be able to send data to any of the clients too, and finally enqueue the incoming data so I can process it when I need to do.<br />
<br />
What the class is going to do is:<br />
<ol>
<li>Open a server socket in a port X</li>
<li>Start a thread that will be listening in port X</li>
<li>When we receive connections it will save the client info (ip/port) to a vector so we can communicate with the client, every client starts a new thread to get the incoming data from each client (it is a blocking-socket server)</li>
<li>The data is stored into two different queues depending if the client has logged in or not, I made that because I will apply different priority for the queues , the main (client updates) must be processed with maximum priority other way clients will be lagging.. in the other hand client login request can wait a pair of seconds without big problems.</li>
</ol>
To achieve that I use two classes, first one is cNetwork, it is the main server, second one os cClient, used to store information from every connected client, the header from both classes are stored in the same file:<br />
<br />
<br />
<network.h><br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#ifndef NETWORK_H
#define NETWORK_H
#define MAXLEN 1024
#include "SDL/SDL.h"
#include "SDL/SDL_net.h"
#include "SDL/SDL_thread.h"
#include <vector>
#include <queue>
#include <iostream>
#include <sstream>
using namespace std;
class cNetwork;
class cClient //the connected clients</pre>
<pre>{
public:
//functions
cClient();//creator
virtual ~cClient();//destructor
void StartThreads();//Start listener thread
static int listener( void *data );//Listener Thread
void Send(const char* Msg);//Send data to client
//variables
cNetwork *_server;//To comunicate with main server instance
TCPsocket socket;//client socket
SDL_Thread *ListenerThread;//The network client thread
int threadReturnValueclient;
Uint16 UID;//Unique identifier
bool Connected;//socket connected?
bool Login; //loged in?
};
class cNetwork//main network server class
{
friend class cClient;
public:
//functions
cNetwork();
virtual ~cNetwork();
void Start(Uint16 MAXUsers, Uint16 Port);
void CleanClient(unsigned int Client);//clean a client so we can use it
static int Master( void *data );//Master listener function/thread
void ClearClients();//Clear disconnected clients
void Finish();//close all client connections and finish server
//variables
queue<std::string> InputQueue;//Here we store received data
queue<std::string> LoginQueue;//Here we store login requests
SDL_sem *ClientsLock; //Semaphore to prevent server from accesing a variable from different threads
cNetwork *myserver;//server pointer
vector<cClient*> Clients;//Here I store clients
SDL_Thread *MasterThread;//The Master thread >> accepts new clients
int threadReturnMaster;//return value for master thread
bool ShutDown;//closing the server?
private:
//private variables
IPaddress ip;//Server ip address
TCPsocket ServerSock; //Server socket
};
#endif // NETWORK_H
</pre>
</div>
<br />
Then I have the client implementation:<br />
<br />
<client.cpp><br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include "network.h"
cClient::cClient()
{
//ctor
ListenerThread = NULL;
Connected = false;
}
cClient::~cClient()
{
//dtor
//Stop the thread
SDL_KillThread( ListenerThread );
//close the socket
SDLNet_TCP_Close(socket);
}
void cClient::StartThreads()
{
//Create and run the thread +
ListenerThread = SDL_CreateThread( &listener, this );
}
int cClient::listener( void *data )
{ //While the program is not over
cout << "Starting client listener Thread..." << endl;
int result;
char in_msg[MAXLEN];
bool quit=false;
while( quit == false )
{
memset(in_msg, 0, MAXLEN); // Clear in buffer
if ( ((cClient*)data)->Connected)//If I'm connected...
{
result=SDLNet_TCP_Recv(((cClient*)data)->socket,in_msg,MAXLEN);//Check for incoming data
if(result<=0)
{
//NO DATA
// TCP Connection is broken. (because of error or closure)
SDLNet_TCP_Close(((cClient*)data)->socket);
cout << "Socket closed..." << endl;
((cClient*)data)->Connected = false;
quit=true;
}
stringstream idmsg;
idmsg << ((cClient*)data)->UID << "#" << in_msg;// I will add the UID from the client to the incoming message
try{
SDL_SemWait(((cClient*)data)->_server->ClientsLock);//lock smaphore to prevent client to freeze
cout << idmsg.str();//only for debuging
if (((cClient*)data)-> Login==true)//Am I loged in?
{
((cClient*)data)->_server->InputQueue.push(idmsg.str()); //I'm logged in
}else{
((cClient*)data)->_server->LoginQueue.push(idmsg.str()); //New player requests
}
SDL_SemPost(((cClient*)data)->_server->ClientsLock);//unlock smaphore
}
catch(exception& e)
{
cout << "QUEUE IN ERROR: " << e.what() << endl;
}
}//if connected
}//while
cout << "Closing client listener thread..." <<endl;
return 0;
}
void cClient::Send(const char* Msg)
{
if (Connected==true)
{
int len;
int result;
len=strlen(Msg+1); // add one for the terminating NULL
result=SDLNet_TCP_Send(socket,Msg,len);
if(result<len) //If I can't send data probably I've been disconnected so....
{
cout << "SDLNet_TCP_Send: " << endl << SDLNet_GetError();
Connected = false;
}
}else{
cout << "Not connected!!" << endl;
}
}
</pre>
</div>
<br />
Notice the client stores the data in two different queues depending if the client has loged in or not, finally we have the main socket server class:<br />
<br />
<network.cpp><br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include "network.h"
cNetwork::cNetwork()
{
//ctor
if(SDLNet_Init()==-1) {//Start SDL_NET
cout << "SDLNet_TCP_INIT: \n " << SDLNet_GetError();
exit(2);
}
//Clean thread variables
MasterThread = NULL;
ClientsLock = NULL;
ClientsLock = SDL_CreateSemaphore( 1 );//semafor protector, previene que mas de un thread vuelque información a la vez a la cola
}
cNetwork::~cNetwork()
{
//dtor
SDLNet_TCP_Close(ServerSock);//Close socket
SDLNet_Quit();//Close SDL_NET
}
void cNetwork::CleanClient(unsigned int Client)//clean a client so we can use it
{
//cout << "cleaning client: " << Client << endl;
Clients[Client]->UID =Client;
Clients[Client]->socket = NULL;
Clients[Client]->_server = myserver;
Clients[Client]->Connected = false;
Clients[Client]->Login = false;
}
void cNetwork::Start(Uint16 MAXUsers, Uint16 Port)
{
//1-initialize MAXUsers clients
//2-Start sock server
unsigned int x;
for (x=1;x<=MAXUsers;x++)
{
Clients.push_back(new cClient());//insert a new client into the clients vector
CleanClient(Clients.size() -1);
}
cout << "OPENING SERVER SOCKET... " << endl;
if(SDLNet_ResolveHost(&ip,NULL,Port)==-1) {
cout << "SDLNet_TCP_ResolveHost:" << endl << SDLNet_GetError();
exit(1);
}
ServerSock=SDLNet_TCP_Open(&ip);
if(!ServerSock) {
cout << "SDLNet_TCP_open: " << endl << SDLNet_GetError();
exit(2);
}
ShutDown = false;
//Create and run the threads
MasterThread = SDL_CreateThread( &Master, this );
}
int cNetwork::Master( void *data )//Master listener function/thread
{
TCPsocket new_tcpsock; //Temporary socket to store incoming connections
new_tcpsock=NULL;
cout << "Waiting for incoming connections... " << endl;
bool doneMain=false;
while(!doneMain)//MAIN LOOP
{
if(!new_tcpsock)//We have a new client incoming
{
new_tcpsock=SDLNet_TCP_Accept(((cNetwork*)data)->ServerSock); // accept a connection coming in on server_tcpsock
SDL_Delay(5);//No new clients, wait a little
}else{
cout << "New client incoming..." << endl;
unsigned int x;
for(x=0;x<((cNetwork*)data)->Clients.size();x++)
{
if (((cNetwork*)data)->Clients[x]->Connected==false)
{
((cNetwork*)data)->CleanClient(x);
((cNetwork*)data)->Clients[x]->socket=new_tcpsock;//asign the socket
((cNetwork*)data)->Clients[x]->Connected = true;
((cNetwork*)data)->Clients[x]->Login = false;
((cNetwork*)data)->Clients[x]->StartThreads();//start client listener thread
break;
}
}//for
new_tcpsock=NULL;//release temporary socket var
}//if new data
if (((cNetwork*)data)->ShutDown==true)doneMain =true;
}//while
cout << "Exiting Main thread..." << endl;
return 0;
}
void cNetwork::ClearClients()//Clear disconnected clients
{
unsigned int x;
bool done = false;
//SDL_SemWait(ClientsLock);
if (Clients.size()>0)
{
x=0;
while (!done)
{
if (!Clients[x]->Connected)
{
Clients.erase(Clients.begin()+x);
// cout << "Number of clients:" << Clients.size() << endl;
if (x>0)x--;
}//if !connected
x++;
if(x>=Clients.size())done=true;
}
}//clients size
}
void cNetwork::Finish()
{
ShutDown =true;
SDL_WaitThread(MasterThread,&threadReturnMaster);
unsigned int x;
for(x=0;x<Clients.size();x++)
{
Clients[x]->Connected=false;//force disconnection
}//for
while (Clients.size()>0)
{
ClearClients();
}
}
</pre>
</div>
<br />
There are many things here, but I will resume it to the maximum, to do that, below there is a simple example to use the class:<br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include "network.h"//socket server class </pre>
<pre> </pre>
<pre>cNetwork NET;
NET.myserver = &NET;
NET.Start(100,55555); //start networking, up to 100 clients on port 55555</pre>
<pre> </pre>
<pre>std::sting text;</pre>
<pre>SDL_SemWait( NET.ClientsLock );
text = NET.InputQueue.front();//take a message out from the queue
NET.InputQueue.pop();
SDL_SemPost( NET.ClientsLock ); </pre>
<pre> </pre>
<pre>NET.Clients[X]->Send("data");//will send "data" to client X</pre>
<pre> </pre>
<pre>NET.Finish();//finish socket server </pre>
</div>
<br />
<ul>
<li>We include the class</li>
<li>Then instantiate it</li>
<li>Start the listener thread (at this moment it is fully functional)</li>
<li>Then I extract a message from the input queue (let's suppose we have a connected client that send it..)</li>
<li>I send a message to the server ("data")</li>
<li>Finally, I close the server</li>
</ul>
Want to test the class? basically start an empty project, add the three files I have described above and then add the example, after you compile the project you will be able to connect just using telnet (telnet localhost 55555)<br />
<br />
That's all for now, in the next post I will mix everything to make the client login a reality, I will make a text based client too and hope everything is clear that way.<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-42554270249423808772012-08-03T23:43:00.004+02:002012-08-03T23:44:12.288+02:00SVN UP! New code repositoryHello again<br />
<br />
Before going any further (and after all the things that happened with Megaupload), I knew I wont be able to continue uploading my project / tools / whatever to 4shared, and yes I was right, in a few days 4shared started to ask for "user accounts" to be able to download things...<br />
<br />
I had to start using another away to store my project.. and I needed a way to control the versions from my project.<br />
<br />
The solution was quite simple (basically because a good friend showed me from the advantages of using subversion aka "svn")<br />
<br />
So I went back to Google.. again.. went to http://code.google.com and signed for a new account, created a new project (http://code.google.com/p/jbfprj/) and voila! I got my own svn server :)<br />
<br />
So now anybody can checkout in my software repository and get the source for my projects, at the moment I just uploaded SimpleSQL:<br />
<br />
<copied from code.google.com><br />
Use this command to anonymously check out the latest project source code:<br />
<div class="box-inner">
<tt># Non-members may check out a read-only working copy anonymously over HTTP.</tt><br />
<tt id="checkoutcmd">svn checkout <b><i>http</i></b>://jbfprj.googlecode.com/svn/trunk/ jbfprj-read-only</tt></div>
<div class="box-inner">
</div>
<div class="box-inner">
<tt id="checkoutcmd">Notice you will need to install subversion: </tt></div>
<div class="box-inner">
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>sudo apt-get install subversion
</pre>
</div>
<div class="box-inner">
<tt id="checkoutcmd">under linux or you can use another client for windows like tortoise-svn...</tt><br />
</div>
<div class="box-inner">
</div>
Anyway, that's all you will need to get the source, and of course, type "<b>svn up</b>" whenever you want to check if there are updates...><br />
<br />
In the next post I'll be back to the server program, but now I'm going to reduce the posts to a size that anybody can handle, starting for login to the server..
</div>Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-63447958227883630072012-08-02T23:51:00.002+02:002012-08-02T23:51:36.561+02:00A class to use MYSQL<After installing and setting up the MySql server ,we need to access the MySql database from code::blocks><br />
<br />
To achieve the objective I'm going to make a class to connect and launch SQL queries to the MySql server , and of course a test project to use the class.<br />
<br />
So the steps to get started are:<br />
<ol>
<li>Open code::blocks</li>
<li>Create an empty project</li>
<li>Add a file and save it "main.cpp"</li>
<li>Add a new class with the wizard and name it "csql"</li>
</ol>
Now we edit the header for class csql (csql.h):<br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#ifndef CSQL_H
#define CSQL_H
#include <mysql.h>//Needed to use MySql
#include <string.h>
#include <sstream>
using namespace std;
class csql
{
public:
MYSQL_ROW row; //Here we store query results in rows
csql(); //constructor
virtual ~csql();//destructor
bool connect(const char * serverip, const char * username, const char * password, const char * database);//connecto to a server , with username and password and select database
void executequery(const char *query);//execute SQL query
bool getrow();//we get a row from the results from a query
private:
MYSQL mysql;//mysql class
MYSQL_RES *res ;//mysql results for queries
};
#endif // CSQL_H
</pre>
</div>
<br />
Basically there are 5 functions: the creator and destructor, a function to connect to the mysql server, a function to execute queries and finally a function to get the result from SELECT queries.<br />
<br />
Now the implementation (csql.cpp):<br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include "csql.h"
using namespace std;
csql::csql()
{
//ctor
mysql_init(&mysql);//start mysql
}
csql::~csql()
{
//dtor
mysql_close(&mysql);//close mysql
}
//We use connect() to connect to the database needed
bool csql::connect( const char * serverip, const char * username, const char * password, const char * database)
{
if (mysql_real_connect(&mysql
,serverip
,username
,password
,database,0,NULL,0))
{
return true;//everything ok
}else{
return false;//connection failed
}
}
void csql::executequery(const char *query)//Execute SQL query
{
mysql_real_query(&mysql,query,strlen(query));
res = mysql_store_result(&mysql);
}
bool csql::getrow()//We extract a row from the result from an SQL query (or get false if empty)
{
if ((row = mysql_fetch_row(res)))
{
return true;//we have extracted a row
}else{
return false; // no rows to extract
}
}
</pre>
</div>
<br />
It is quite simple to follow the code:<br />
<ul>
<li>csql() (constructor) just initializes the mysql class used to work with the DB</li>
<li> ~csql() (destructor) frees the class, closing any active connection</li>
<li>connect() connect to the server, using 4 parameters: the server IP, the username, the password and the database to connect (it returns true if the it connects ok, false when there is a failure)</li>
<li>executequery() used to launch SQL queries, just plain SQL commands like "select * from table"</li>
<li>getrow() get a data row from the results of a select query, if there are rows it will return true and we can access the data columns with csql_instance.row[index], other way it returns false</li>
</ul>
And finally, to use the class I wrote a pair of examples (main.cpp): <br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include <iostream>
#include "csql.h"
using namespace std;
int main(int argc, char *argv[])
{
csql sql;//we use the sql class
cout << "Connecting to database.." << endl;
if (!sql.connect("localhost","root","rpgdata","rpgdata"))//we connect using the serverip, username, password and database
{
cout << "Error connecting to database" << endl;
return -1;
}
cout << "DELETING.." << endl;
sql.executequery("delete from accounts");//executing delete query
sql.executequery("select * from accounts");//executing select query
while (sql.getrow())
{
cout << sql.row[0] << " " << sql.row[1] << " " << sql.row[2] << " " << sql.row[3] << " " << sql.row[4] << endl;
}
cout << "INSERTING Jorge.." << endl;
sql.executequery("insert into accounts values (NULL, 'Jorge','jorge@hotmail.com','pass',NULL)");//executing insert query
sql.executequery("select * from accounts");//executing select query
while (sql.getrow())
{
cout << sql.row[0] << " " << sql.row[1] << " " << sql.row[2] << " " << sql.row[3] << " " << sql.row[4] << endl;
}
cout << "INSERTING Paul.." << endl;
sql.executequery("insert into accounts values (NULL, 'Paul','paul@gmail.com','pass',NULL)");//executing insert query
sql.executequery("select * from accounts");//executing select query
while (sql.getrow())
{
cout << sql.row[0] << " " << sql.row[1] << " " << sql.row[2] << " " << sql.row[3] << " " << sql.row[4] << endl;
}
return 0;
}
</pre>
</div>
<br />
I make an instance from the mysql class, then I connect to the server, clean the table "accounts", and then I insert a pair of data rows, I display the results from select queries too, there are other SQL commands like UPDATE which I have not used, but I think that it is quite enough to show the use from the class.<br />
<br />
<Notice that I am using the password "rpgdata", the database "rpgdata", the table "accounts".. if you don't use the same database or table names, the example wont work(I explained how to set it up in the previous two posts)><br />
<br />
Finally there is one final thing you need to set up to make the project compile:<br />
<br />
<ul>
<li>Go to "project" > "build options"</li>
</ul>
<br />
<ul>
<li>Then in "compiler" > "other options"</li>
</ul>
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>`mysql_config --cflags`
</pre>
</div>
<br />
<ul>
<li>And in "linker" > "other linker options"</li>
</ul>
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>`mysql_config --libs`
</pre>
</div>
<br />
Other way the compiler wont find mysql and it will refuse to work...<br />
<br />
<So basically we have a simple class to use the freshly new installed MySql server, now we can use it in any project, but obviously I'm going to add it to the socket server, in the next post I will show another new I'm going to use to host the project development...><br />
<br />
See you!Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-37197071507477590522012-08-02T00:12:00.001+02:002012-08-02T00:12:06.934+02:00MYSQL + Command Line<In the last post I spoke about my decision to start using MySql , now I will speak about how to set up a simple test database using the command line prompt><br />
<br />
<b>CONNECTING TO THE SERVER</b><br />
<br />
MySql has a basic tool to set up (almost) everything you need from your SQL server.<br />
<br />
After installing MySql you just need to use the command:
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>mysql -h ServerIp -u username -p
</pre>
</div>
<br />
That will connect to the mysql server with ServerIp, and try to validate,
if you don't write the IP it will default to localhost, the username is
the username used to login into the server, and finally -p makes mysql
to ask for the password of the username:
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>jbea@eeepc1005HA:~$ mysql -h localhost -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 39
Server version: 5.5.24-0ubuntu0.12.04.1 (Ubuntu)
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
</pre>
</div>
Here we are, logged in..<br />
<br />
<b>CREATING DATABASES AND TABLES</b><br />
<br />
Next step would be very simple, create our database:<br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> CREATE DATABASE rpgdata;</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Query OK, 1 row affected (0.00 sec)</span>
</pre>
</div>
<br />
Notice the semicolon ";", every instruction in the mysql command prompt must finish with ";", it's the end of sentence command<br />
<br />
It will create a new database "rpgdata" , then we can check the databases in our server:<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> SHOW DATABASES;</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+--------------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| Database |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+--------------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| information_schema |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| mysql |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| rpgdata |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+--------------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">3 rows in set (0.00 sec)</span>
</pre>
</div>
<br />
We can delete the databases with the command:
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql>DROP DATABASE rpgdata; </span>
</pre>
</div>
<br />
After creating a database and before we can actually work with it we need to "use" it with the command: <br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql>USE rpgdata; </span>
</pre>
</div>
<br />
Next step would be creating the tables to store the data: <br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql>CREATE TABLE table (datafield1, datafield2..); </span>
</pre>
</div>
Example:<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> CREATE TABLE accounts (</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> -> id INT AUTO_INCREMENT,</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> -> fullname VARCHAR(60),</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> -> email VARCHAR(120),</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> -> password VARCHAR(30),</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> -> PRIMARY KEY (id));</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Query OK, 0 rows affected (0.06 sec)</span>
</pre>
</div>
<br />
Now we can check the tables we have in our database: <br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> SHOW TABLES;</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+-------------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| Tables_in_rpgdata |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+-------------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| accounts |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+-------------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">1 row in set (0.00 sec)</span>
</pre>
</div>
<br />
And another interesting thing: we can check the database structure with the command: <br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> DESCRIBE accounts;</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+----------+--------------+------+-----+---------+----------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| Field | Type | Null | Key | Default | Extra |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+----------+--------------+------+-----+---------+----------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| id | int(11) | NO | PRI | NULL | auto_increment |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| fullname | varchar(60) | YES | | NULL | |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| email | varchar(120) | YES | | NULL | |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| password | varchar(30) | YES | | NULL | |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+----------+--------------+------+-----+---------+----------------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">4 rows in set (0.00 sec)</span>
</pre>
</div>
<br />
<br />
<b>DATA HANDLING</b><br />
<br />
At this point, we can start using standard SQL sentences to handle the data: <br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span style="color: black;"><span style="font-family: Arial;">>INSERT INTO > Insert data</span></span></pre>
<pre><span style="color: black;"><span style="font-family: Arial;">>UPDATE > update data</span></span></pre>
<pre><span style="color: black;"><span style="font-family: Arial;">>DELETE FROM > delete data</span></span></pre>
<pre><span style="color: black;"><span style="font-family: Arial;">>SELECT FROM > Get data </span></span>
</pre>
</div>
<br />
A pair of examples: <br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6103904055143933" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span><span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> INSERT INTO accounts VALUES</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> -> (NULL, 'Jorge Bea Frau','jbeafrau@gmail.com','password');</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Query OK, 1 row affected (0.00 sec)</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql></span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql> SELECT * FROM accounts;</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+----+----------------+--------------------+----------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| id | fullname | email | password |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+----+----------------+--------------------+----------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">| 1 | Jorge Bea Frau | jbeafrau@gmail.com | password |</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">+----+----------------+--------------------+----------+</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">1 row in set (0.00 sec)</span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"></span>
<span style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql></span>
</pre>
</div>
<br />
SQL Language is almost a programming language itself so it's way beyond my hand to teach the language, anyway I will explain the sentences when I use them so you don't have to worry about it.<br />
<br />
<b>BACKUPS AND RESTORES</b><br />
<br />
Finally, to make a backup from a database to a plain text file and restore it later we have two commands:<br />
<br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6235897149757301" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysqldump -h localhost -u root -p DATABASE > backupfile.sql</span>
</pre>
</div>
To make a backup from a database to a file... <br />
<br />
<div id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre><span id="internal-source-marker_0.6235897149757301" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">mysql -h localhost -u root -p </span><span id="internal-source-marker_0.6235897149757301" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">DATABASE < backupfile.sql</span>
</pre>
</div>
To restore a database from a backup file<br />
<br />
<Notice that in both commands you have to execute the commands from the terminal window, not from the mysql prompt><br />
<br />
And that's all for now, that's all we are going to need to start using the mysql server, creating our database and the tables inside, we can now design our game database, and we could even insert the desired data inside (I Wont recommend that!), but instead we are going to use c++ to connect to the mysql server and launch SQL sentences...<br />
<br />
In the next post: Using mysql from c++ + code::blocks.<br />
<br />Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-17146477994971960772012-07-30T15:28:00.003+02:002012-07-30T15:28:52.121+02:00Finally, MYSQL + code::blocks!Hello everybody, today I'll make a "postmortem analysis" and will install and set up MySql server<br />
<br />
<Been out for a long time <again>, had many things to do and my project got stucked again, but it didn't get forgotten! I have been reading all the code again and had time to think about it, the things I have done right and which things should I change / improve, and made an small list:><br />
<br />
GOOD THINGS<br />
<ol>
<li>The server actually works!</li>
<li>Client program able to create players, connect, and "move around" </li>
<li>Worked quite fast in a desktop computer using small amounts of RAM</li>
</ol>
BAD THINGS<br />
<ol>
<li>Ugly code, I feel really ashamed about that, but it is the result of writing code in a "fast 15 min way"</li>
<li>Server is unstable, yeah, after fixing many, many bugs it did worked, but still had things to fix.</li>
<li>I was not using a real scenario , data was not being loaded from server, so player creation, maps, etc was everything client-side, obviously that is not good, for many reasons (security, for example)</li>
<li>World didn't had persistent data, players, objects, etc were not stored after closing client program</li>
</ol>
In other words I just did a network demo, I was so anxious to make the server work with thousands of clients that I didn't realized I was starting to loose the focus in my objective: MAKE THE GAME!<br />
<br />
So I took a hard decision, dropped the code and to make a second server with all the good things the first server had + all the things it SHOULD HAVE like persistent data, and a true server-client model.<br />
<br />
Having persistent data meant to use some kind of static storage, so I thought in using just plain files plus standard c++ io functions to write data, but I dropped the idea fast because there are already libraries to solve the "writing another text parser" like <a href="http://www.grinninglizard.com/tinyxml/">TinyXml</a> , but after playing with that again I found that if I used that library I will be making two times the work because:<br />
<ol>
<li>First I will have to write all the data in .xml files</li>
<li>To later rewrite the code again to switch to a real database..</li>
</ol>
I went back to my very first objectives and the name <a href="http://www.mysql.com/">MySql</a>, came to my mind...<br />
<br />
<span style="color: red;"><NOTE</span>: I have completely dropped support for windows in the server part,
that means I wont be posting how to install and make it run under
Windows OS family, basically I made that because that's the OS I will be
using to make and run the server and I cant loose more time in
something I wont be using, although anybody could check how to download
and install the required libraries for the OS you choose..><br />
<br />
So I installed the mysql server:<br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>sudo apt-get install mysql-server
</pre>
</div>
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">It just asked me for the "root" database password, it is very important because it will be used to connect to MySql and use the database, NOTE: it is not the linux root account so you can / should have different passwords </span>.<br />
<br />
I installed too MySql tuner:<br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>sudo apt-get install mysqltuner
</pre>
</div>
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">Used to get advice to tune the databases </span><br />
<br />
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">And the client libraries:</span><br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>sudo apt-get install libmysqlclient-dev
</pre>
</div>
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline;">Used to connect from the client app </span><br />
<br />
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; text-decoration: none; vertical-align: baseline;">To check that the MySql server is running:</span><br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>sudo netstat -tap | grep mysql
</pre>
</div>
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><br />
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;">You can restart the service with:</span><br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>sudo service mysql restart
</pre>
</div>
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><br />
<span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: normal; text-decoration: none; vertical-align: baseline;"> </span><span id="internal-source-marker_0.5001132039293757" style="background-color: transparent; color: black; font-family: Arial; font-size: 15px; font-style: normal; font-variant: normal; font-weight: bold; text-decoration: none; vertical-align: baseline;"> </span><br />
<You can see installing MySql server is quite simple, in the next post I will write about comand-line database management, and finally start using it with code::blocks>Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-48468904758884148532012-04-03T22:59:00.004+02:002012-04-03T22:59:47.574+02:00Rpg Client update: Rotate playersWelcome back!<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHVJriZESKF48QVY9Hu2rkjo4-s6x5ffERjX45EyVMH_9TxVyYUV1FXBFfXCdMuwuu4jfcvzBuK_iTAqy1xBu1CTTh4pn5SOalYApOmLvv2fikiWna9jzgB1qjEvhEV4lMOIm25MvKOXfb/s1600/bots_angle.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" dea="true" height="480" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjHVJriZESKF48QVY9Hu2rkjo4-s6x5ffERjX45EyVMH_9TxVyYUV1FXBFfXCdMuwuu4jfcvzBuK_iTAqy1xBu1CTTh4pn5SOalYApOmLvv2fikiWna9jzgB1qjEvhEV4lMOIm25MvKOXfb/s640/bots_angle.png" width="640" /></a><br />
<b>Player's point of view is quite clear now...</b><br />
<br />
Since I decided to continue the project I started to think again in all the things I could make to improve it, and the first thing was to make it clear where players / foes were looking at, it's basic to make you know:<br />
<ol>
<li>Where are you going (the red dot did not helped a lot)</li>
<li>Where are going all the other players / enemies</li>
<li>Can I ambush somebody?, am I being ambushed?</li>
</ol>
To make client rotate images I just needed a function to rotate a tile certain angle, I didn't had to modify the server code because I already included angle in the players data, I thought how to rotate that and finally I decided to use a library from a good friend that was open source and based in the standard library SGE:<br />
<br />
<a href="http://code.google.com/p/sprig/">SPRIG: The SDL Primitive Generator</a><br />
<br />
A great job from <a href="http://code.bluedinosaurs.com/">Jhonny D</a><br />
<br />
To use the library you will need the subversion client, (in linux "sudo apt-get install subversion", in Windows you can use <a href="http://tortoisesvn.net/">Tortoise SVN client</a>, for example)<br />
<br />
<u>To download / install it under linux:</u><br />
svn checkout <a href="http://sprig.googlecode.com/svn/trunk/">http://sprig.googlecode.com/svn/trunk/</a> sprig<br />
cd sprig<br />
make<br />
sudo make install<br />
<br />
(Haven't tested it under windows yet)<br />
<br />
I created a new function: <b>RotateBlitTileset</b>( x,y,image,angle), that functions draws the rotated tile (image) at x,y.<br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>void Engine::RotateBlitTileset(int x, int y, int tile, float Angle) //Rotate and Blits a tile from our tileset to the screen
{
SDL_Surface * tmpBlit = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCCOLORKEY |SDL_RLEACCEL,TileSize,TileSize,32,0,0,0,0);
SDL_Surface * tmpBlit2 = SDL_CreateRGBSurface(SDL_SWSURFACE|SDL_SRCCOLORKEY |SDL_RLEACCEL,TileSize,TileSize,32,0,0,0,0);
//1-fill temporary surface with pink
SDL_FillRect(tmpBlit, 0, SDL_MapRGB(tmpBlit->format, 255, 0, 255));
start.x= (tile%10)*TileSize; //Column = tile % 8 (0-7)
start.y= (tile/10)*TileSize; //Row = tile / 8 (0-7)
start.w=TileSize;
start.h=TileSize;
end.x =0; // X
end.y =0; // Y
end.w = TileSize;
end.h = TileSize;</pre>
<pre> //2-Blit the desired tile to the temporary surface
SDL_BlitSurface(tileset, &start, tmpBlit, &end);
//3-I call sprig function SPG_Rotate() to rotate the temporary surface and get the resulting surface into a 2nd temporary surface
tmpBlit2 = SPG_Rotate(tmpBlit, Angle -90, SDL_MapRGB(tmpBlit-> format, 255, 0, 255));
SDL_SetColorKey(tmpBlit2,SDL_SRCCOLORKEY |SDL_RLEACCEL,SDL_MapRGB(tmpBlit2-> format, 255, 0, 255));//set the color key
start.x=0;
start.y=0;
start.w=TileSize;
start.h=TileSize;
//set the cliping for the destination surface (the screen)
end.x =x; // X
end.y =y; // Y
end.w = TileSize;
end.h = TileSize;
SDL_BlitSurface(tmpBlit2, NULL, screen, &end); //Blits the rotated tile to the screen
SDL_FreeSurface( tmpBlit);
SDL_FreeSurface( tmpBlit2);
}
</pre>
</div>
<br />
Notice I can't just call Sprig rotate function because I would get a rotated tile with pink background, so I have to use the tmp surface to set the color-key, that way is not optimized at all so I will think in a way to make it faster later, but at the moment is ok.<br />
<br />
In the next post: Let's chat!Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-34481288048356488992012-03-27T23:59:00.000+02:002012-03-28T00:01:30.381+02:00I'm alive!!I could tell you I had a very bad car accident, maybe that I got into the drugs , got kidnapped or abducted but I really can't say other thing than the truth:<br />
<br />
I have not made anything in the project for about two months :(<br />
<br />
Got quite frustrated trying to make the project to work the non-blocking way, and in fact I made it to "work" quite easy, I was very happy because I thought I could make the server work faster and use less resources than I was using...<br />
<br />
WRONG!, server worked fine with a low load (say less than 50 users), but when I started to add more users it just collapsed with nasty segmentation fault errors, sometimes when a client disconnected it just blocked the server, I didn't had all those problems with the "old" server and I although I tried to debug the code, errors never went away..<br />
<br />
But that's not the worst thing, worst think is performance was poor.. I never felt the non-blocking approach was faster, basically because my blocking approach used many, many threads, a good approach if you use a multi-core processor, but the non blocking used only 3-4 threads for everything, with separate functions like accepting new clients, updating player states or sending data, so some threads have little load while other threads couldn't handle the load at all.<br />
<br />
What happens when you have problems? usually it starts to appear more like mushrooms (Damn Murphy's law ), and I was just trying to solve other problems that were not related to the blog...<br />
<br />
And then I let the blog die slowly, but even without posting more blogs many people entered and read it, and today I arrived to 3k visits and I knew I had to do something, like trying to reanimate the zombie-blog.<br />
<br />
Then I remembered a comment I got from wise <a href="http://www.blogger.com/comment.g?blogID=1792734122980275490&postID=2962704196701667279&isPopup=true" target="_blank">Amit Patel</a> : How many users do I plan to have? maybe the problem is not being able to handle 10k users·<br />
<br />
Now I can say I was distracting myself from my biggest objective, actually making the game!!! so I put my hands on the blocking sockets code again and re-started again, it has been hard, but in this week I expect to launch two updates for the game that will make it a little more user friendly and usable..<br />
<br />
Thanks for reading and see you soon (promise)<br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com1tag:blogger.com,1999:blog-1792734122980275490.post-75977550238630749112012-01-27T19:18:00.001+01:002012-01-28T00:04:48.179+01:00Blocking-sockets Windows binaries released! I have compiled the projects under MS Windows, surprisingly almost everything worked as expected and the binaries are available in <a href="http://www.blogger.com/goog_1641507343"></a><a href="http://jbfproject.blogspot.com/p/downloads.html"> Downloads</a>(-RPGServer / Client / Bot Tutorial ->Windows Binaries), feel free to download and test it.<br />
<br />
There were only two problems:<br />
<ol>
<li> Server include paths were wrong, I had <SDL/SDL.h> so I replaced them with <SDL.h> and compiled fine</li>
<li>The bot was giving me errors in the line srand(time(NULL)), solved with a #include <time.h>, curious it worked fine under linux.</li>
</ol>
When running there is only an issue: no cout output under windows so server starts, and actually works! but there is no output at all, anyway it's ok to test.<br />
<br />
The server has certain limits like not being able to accept more than
1018 clients and to use too much resources, but if you plan to work with
a limited amount of users (200-300) it will make the job.<br />
<br />
I would be glad to hear (constructive) comments about the code, the bugs you may found and well, basically your opinion.<br />
<br />
Thanks to everybody!Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-21017198766226546362012-01-27T01:35:00.000+01:002012-01-28T00:05:09.290+01:00Blocking-Sockets server code releasedHello again!<br />
<br />
After I decided to stop the development for a while I tought it would be nice to share the code with everybody interested, so after a huge cleanup (probably not enought) I have uploaded the code for the server, the client and a silly bot I did to test multiple client connections, they are now in <a href="http://jbfproject.blogspot.com/p/downloads.html">Downloads</a> (-RPGServer / Client / Bot Tutorial -> Source code), feel free to download and test it.<br />
<br />
The server has certain limits like not being able to accept more than 1018 clients and to use too much resources, but if you plan to work with a limited amount of users (200-300) it will make the job.<br />
<br />
Server is <strike style="color: red;">un</strike>tested under windows <span style="color: red;">(it works!)</span>, client and bot wont care too much for the OS (will work in linux / windows), I don't have a machine with Mac OS X to test so I couldn't test it (any volunteer to try with an apple computer?)<br />
<br />
I would be glad to hear (constructive) comments about the code, the bugs you may found and well, basically your opinion.<br />
<br />
Thanks to everybody!Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-29627041967016672792012-01-03T23:58:00.000+01:002012-03-25T17:28:09.523+02:00STOP & GO<b>Blo</b><b>cking socket limits</b><br />
<br />
After a long time trying to fix errors / improve performance I have arrived to a sad point: My server with blocking sockets wont support more than 1.018 users, I arrived that limit making an stress test trying to arrive to the 2.000 users barrier, no more clients were accepted after client 1.018.<br />
<br />
The problem comes from the design I choose to make the server, I was using blocking sockets, that means for every client we need a thread to wait for data, 1.018 users = 1.018 threads + threads used by the server reached the default limit in Linux (1.024), I have been reading about that , and I know that limit can be modified but it's not a real solution for the problem because my test computer used 90% processor time to handle "only" 1.000 users, so I have to switch to another technology..<br />
<br />
That technology is non-blocking sockets, because basically with a single thread you could theoretically handle 1.000 maybe 2.000 connected users, I have been speaking with people that has worked in the game industry and for linux servers the best / fastest way is to use <a href="http://linux.die.net/man/4/epoll">epoll</a> , epoll is basically used to handle I/O from many file descriptors (connections) in real time, but using epoll to me would have meant throwing away all what I have been working on in the last 3 months.... (Thanks Neils for showing me the right way!)<br />
<br />
Finally I decided to use <a href="http://www.libsdl.org/projects/SDL_net/docs/SDL_net_41.html">socket sets</a> , that is the SDL_net non-blocking approach for that problem , so basically I have to re-write all the networking code for my server...<br />
<br />
I have decided to take a rest in the development and I have started a collaboration with a friend to make a multiplayer platformer, it is very good because I have time to think in other things and learn, I'm just finding that I was making many errors and many things could be improved. <br />
<br />
See you soonAnonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com3tag:blogger.com,1999:blog-1792734122980275490.post-13070750785552231332011-12-10T23:48:00.001+01:002011-12-19T14:06:56.073+01:00So I want make an MMORPG, Where do I start from? PART 4<b>Messaging and optimizations:</b><br />
<br />
<b><Messaging:></b><br />
<br />
Networking is the core of an
mmorpg, and just in the top of the network we have the messaging system.
What we need is to create a way to communicate between server and
clients.<br />
<br />
Clients will send commands to the server for
example: move forward, turn right, atack!... In the server we could have
comands to send the map, the clients data like player / npc position,etc...<br />
<br />
Most of the people (should) use serialization to send data, for example an item could be packed in an object / serialize it and send over the net, in the destination it would be deserialized and here we have our object/item again, but I have used another way to transfer messages that is hard to code but easier to understand: Plain-text messages.<br />
<br />
Probably now you are wondering about how does it works, suppose we want our client to send to the server we are moving forward, then we will just send a command telling the server we have pressed "forward", suppose we decide the text command is going to be "/acce", when the server receives a string "/acce" from our client it will understand the client is moving forward so it will move the client forward in the map and return the new updated position to the client; The server will send "/ping" to the clients every x seconds ,when the clients receive "/ping" it will return "/pong" to measure delay in the communication between server/clients.<br />
<br />
What are the advantages when using this method? basically it simplifies debugging , it's easier to understand an incoming packet when you can actually see the command and not a binary-format hex value, basically it is good for didactic purposes.<br />
<br />
The disadvantages? performance and scalability , "/acce" uses 5 bytes to send "forward", too much for a simple commands in the other side for every new command you have to modify both client and server, that can be overwhelming!<br />
<br />
I resume here all the commands I used for the demo: <br />
<br />
<b>Client side:</b><br />
<ul>
<li>/nick > Set players nickname</li>
<li>/imag > Set players image</li>
<li>/acce > Move forward</li>
<li>/dece > Move backward</li>
<li> /righ > Turn right</li>
<li>/left > Turn left</li>
<li>/idle > Stay idle</li>
<li>/pong > Answer a /ping request</li>
<li>/quit > Exit server</li>
</ul>
<br />
<b>Server side:</b><br />
<ul>
<li>/SUID > Send Unique identifier to the player</li>
<li>/upda > Send non-player updates (X,Y,Nicknames...)</li>
<li> /updb > Send player updates (X,Y...)</li>
<li>/ping > Send a /ping request to calculate client latency</li>
<li>/kill > Sent when a player logoffs</li>
</ul>
So we have our server running, in our client we create a player and then connect to the server, then the client will wait until our server sends "/SUID" with the UID for our client, the UID wont change until we logoff, after receiving the UID our client will send our nick and image, that is how our "enemies" will see us, then we are ready to explore.<br />
<br />
We will start moving around, when we move we will be sending "/acce", "/dece", "/righ" and "/left" to the server that will update our position in the map, if we don't move a "/idle" message will be sent, when the server updates our position it will mark if the client has changed state so it will send the command "/upda" with our updated x and y to the clients in a range (500px), so server wont send updates to clients that can't see our moves, that will limit too network traffic.<br />
<br />
When a clients exits the game it sends a "/quit" to the server, server will clean the players data and then it will send a "/kill" command to the clients so they will clean the exiting client...<br />
<br />
<i><9 messages for the client + 5 messages for the server = total 14 diferent messages! , Probably the simplest messaging system you will have ever seen></i><br />
<br />
<br />
<b><Optimizations:></b><br />
<br />
After I made the server I saw two simple ways to improve performance: first one in the client second one in the server:<br />
<ol>
<li>In the client I was sending 25 messages/ second to the server: I was sending data no mather if it was moving or if it was idle, but I thought that instead sending messages all the time I could only send data when a change was detected, for example: the client is idle, so the first time, it will send "/idle", but if it keeps standing still it wont keep sending "/idle", server will save the command until a new one arrives, so after a while I start to move forward, I send a "/acce" to the server first time, but again if I keep on moving forward it wont send again "/acce".. that divided outgoing messages from 25 to 2 or 3 messages when moving and 0! standing still.</li>
<li>In the server I checked the messages and found that "/upda" >> (client updates) was about 99% of the outgoing traffic, that generated a huge problem when a client was in a crowded area, suppose there are 50 clients near, all them are moving so every client is generating 50 updates / frame, with a frame rate of 20 /s that was 50 * 50 * 20 = 50.000 messages in a second!!! that was making the server collapse, so I had an idea, why not nest packets? when a "/upda" is generated I made the server to don't send that message instantly , instead of that it "packed" into a bigger message, when more "/upda" messages arraived they were packed up to 10 updates in a bigger one, so in the same "crowded" are messages sent will be reduced to 5.000, that was much more reasonable.</li>
</ol>
With that pair of improvements server was able to handle 1000 clients at the same time with almost no delays , traffic had spikes of 18.000 incoming messages and 200.000 messages sent in a second, but then I reached blocking socket's limits...<br />
<b><br /></b><br />
<b><Blocking versus non blocking sockets in the next post></b><br />
<br />
<br />Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-15850682617542921332011-11-28T22:56:00.001+01:002011-12-19T14:08:38.621+01:00So I want make an MMORPG, Where do I start from? PART 3<It had been a long time since I made my last post , part of the problem was because I've been on a trip to Paris (A city everybody should visit at least once in their life), another part of the problem is my fight with non - blocking sockets, but now i'm back and I feel refreshed , with energy to continue with the project.><br />
<br />
Today I'm going to speak about a few things: the server structure ,about messaging and finally about blocking sockets vs non blocking sockets:<br />
<br />
<b>Server Structure:</b><br />
<br />
I plan to make my server architecture based in something like that:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOafObpc6lhEQV_s7UQUHEe-sh_HF-g_rwx7hC4UAWMFK426tS_EKo5voNa8xK4SSe6rLnXJscbmInivqKUv2xCarSHgeW3FIN37jR9hherDPKwCcH6Uj97fGy3iZBfah0vs2L-HtSJB5o/s1600/server_structure.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOafObpc6lhEQV_s7UQUHEe-sh_HF-g_rwx7hC4UAWMFK426tS_EKo5voNa8xK4SSe6rLnXJscbmInivqKUv2xCarSHgeW3FIN37jR9hherDPKwCcH6Uj97fGy3iZBfah0vs2L-HtSJB5o/s640/server_structure.png" width="640" /></a></div>
Clients (a.k.a. players) will connect to a login/ authentication server , when validated they will connect to the proxy server, proxy will redirect players to the less loaded server, (balancing server load), server instances will be deployed across the servers on demand ( if a server is more powerful it could handle more instances), all server instances + login server + proxy srv will access the SQL server to write /read all persistent data to be stored, such as:<br />
<ul>
<li>Usernames / passwords for the login server</li>
<li>Maps , players and objects for the server instances </li>
<li>Number of instances, server instance sockets and health status of the instances (load and failures) for the proxy server.</li>
</ul>
That is a draft of the design I plan to do, at the moment I'm just working to make a server instance + sql server working, the remaining features will be done later (LOGIN / PROXY).<br />
<br />
<b><Messaging in the next post></b>Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-26141984378762743732011-11-22T19:05:00.001+01:002011-11-22T23:35:49.734+01:00So I want make an MMORPG, Where do I start from? PART 2Welcome back to the MMORPG series, part 2!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7oKkI55PwIvu05Sqtr5t1Gm2JS8XbHhiLPM_2sWDxUMAtaXhufSJTDqMx5im7o8lD8SIqItdAkaVxMllxf7ZL8qHysP_zwtOgggd_V6Jefpxe8xbOovr5D6Bo5iojL8tUttdi9SnGvfSQ/s1600/StressTest100.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="475" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7oKkI55PwIvu05Sqtr5t1Gm2JS8XbHhiLPM_2sWDxUMAtaXhufSJTDqMx5im7o8lD8SIqItdAkaVxMllxf7ZL8qHysP_zwtOgggd_V6Jefpxe8xbOovr5D6Bo5iojL8tUttdi9SnGvfSQ/s640/StressTest100.png" width="640" /></a></div>
<br />
<Incoming connections....><br />
<br />
After expending one year to learn c++ and SDL I felt ready for the next step: Networking.<br />
<br />
I did a chat server just to learn how SDL_net works, It is very interesting and I recommend to try to code one to everybody who dares to create an RPG/MMORPG server because it is basically the same with lower processing needs..<br />
<br />
In a chat server (basically ) what happens is:<br />
<ol>
<li>Clients connect to the server</li>
<li> They Login with user name / password</li>
<li>Every time they type something and press <ENTER> message is sent to all the other connected clients.</li>
</ol>
(I'm not including here channels and other things... it is just for demonstration purposes only) <br />
<br />
If you want you can <a href="http://jbfproject.blogspot.com/p/downloads.html">Download</a> the sources for the server and client and test it, (Unfortunately it only works in Linux because if you run it under windows, it will redirect all the output to a file, so basically is useless..).<br />
<br />
But for the MMORPG server I had to analyze it before starting....<br />
<br />
What happens (basically )in a MMORPG server is:<br />
<br />
(Client side:) <br />
<ol>
<li>Clients connect to the server</li>
<li> They Login with user name / password (Or they can create a new user...)</li>
<li>Wait for the server to send UID (See below), and world data</li>
<li>Transmit actions to the server (update position, use skills, pic objects, attack, etc)</li>
<li>Update world state from data received from the server.</li>
<li>Goto point 4...</li>
</ol>
(Server side:)<br />
<ol>
<li>Allocate resources to accept and process data from incoming clients (That includes queues and threads to process data)</li>
<li>For every client that logs into the server, assign an Unique identifier that is not going to change until client disconnects, the UID is going to be the identifier for all the process in the server (and the client too), the client will receive too the basic world data to start playing (like map data, players and enemies...)</li>
<li>Server processes incoming data from connected clients (that includes moving around / and all the skills the player have), for example a player moves forward, server receives a message from client(x) that wants to move forward, so it's going to increase client(x)->Speed</li>
<li>Update world state , here it comes were timing is important, the amount of times a world update is applied will change the speed of the game for ALL PLAYERS, for example, players wont send position changes to the server, but move forward, backward, turn right/left commands, what happens when a world update is executed is that clients will move according to their speed and direction and update X/Y position, so no matter if a client tries to hack the client to run at 100 FPS and not the 25FPS set as default, it wont run faster...</li>
<li>Make a list of the players that have changed state (position, skills used)..</li>
<li>Send updated data from the clients with changed state to all the clients connected and in a X range...</li>
<li>Go to point 3.... </li>
</ol>
I know it is a very raw way to describe what the server does, and you may be missing many features such as maps, skills, enemies / NPCS, AI, etc... but my aim is to make it a simple yet stable network server, then I will add the persistence to do world with a database (Mysql).<br />
<br />
To describe how my server works I'm going to explain how it evolved so it's easier to understand why I changed things...<br />
<br />
So let's start to speak with the 3 versions / milestones my server has reached:<br />
<br />
<b><Version Number 0.1:></b><br />
<br />
<b>Classes:</b><br />
<ul>
<li>cSockServer: Stores global data , a vector to store all the clients connected, server socket, etc...</li>
<li>cSockClient:Stores data for every client such as socket to communicate</li>
</ul>
<b>Threads:</b><br />
<ul>
<li>1x Master thread: Master thread listen for the clients and assigns a new socket to everyone.</li>
<li>1xProcessor thread:It processes the data into the input queues and updates wold data</li>
<li>1xUpdater thread: Insert updated data to the output queues</li>
<li>1xListener Thread/Client:listen for incoming data and inserts it into the Input queue.</li>
<li>1xSender thread/Client:Sends data from the output queue to the client.</li>
</ul>
<b>Queues / vectors:</b><br />
<ul>
<li>Clients vector:Here I store clients data (sockets, UIDs, etc)</li>
<li> Input queue:Every client has one, used to store incoming data</li>
<li>Output Queue:Every client has one, used to store outgoing data</li>
</ul>
<b>Good things of the design:</b><br />
<br />
<ul>
<li>Very simple.</li>
<li>Functional.</li>
</ul>
<br />
<b>Bad Things of the design: </b><br />
<br />
<ul>
<li>Very bad performance, when there was more than 3 clients connected you started to feel it lagging even working with the loop-back interface...</li>
<li>There is no time control, so the server will have to be confident in the clients <Horrid mistake></li>
<li>Wasted data: Two threads per client, two queues per client.. too much </li>
</ul>
<b>What I learned from this version:</b><br />
Threads are a must when speaking of a socket server, so in this very first version what I saw is I needed to use them in a more efficient way, I was using many threads to just send and receive data to the client but only three to process data.. other big mistake was to use so many queues in the clients, it was a pain in the a** to check them and probably not efficient at all.., with all this things in my head I decided to make an updated version:<br />
<br />
<br />
<b><Version Number 0.1.7:></b><br />
<br />
<br />
<b>Classes:</b><br />
<br />
<ul>
<li>cSockServer: Stores global data , a vector to store all the clients connected, server socket, etc...<br />
</li>
<li>cSockClient:Stores data for every client such as socket to communicate</li>
</ul>
<b>Threads:</b><br />
<ul>
<li>1x Master thread: Master thread listen for the clients and assigns a new socket to everyone.</li>
<li>2xProcessor thread:It processes the data into the input queue and updates wold data</li>
<li>1xUpdater Thread, inserts into output queue the data to send</li>
<li>XxSender threads: Send data from the output queue</li>
<li>1xListener Thread/Client:listen for incoming data and inserts it into the Input queue.</li>
</ul>
<b>Queues / vectors:</b><br />
<ul>
<li>Clients vector:Here I store clients data (sockets, UIDs, etc)<br />
</li>
<li> Input queue:One in the server, used to store incoming data</li>
<li>Output Queue:One in the server, used to store outgoing data</li>
</ul>
<b>Good things of the design:</b><br />
<br />
<ul>
<li>Centralizing queues make it to waste less data.</li>
<li>Having more threads to process data makes it to be able to handle more clients (watch the screen-shot in the top of the post), 101 clients connected...</li>
<li>Timing centralized in the server, more secure now<br />
</li>
</ul>
<br />
<b>Bad Things of the design: </b><br />
<br />
<ul>
<li>Still bad performance,after adding 20 clients it started to degrade performance no matter how many threads you added to the server</li>
</ul>
<b>What I learned from this version:</b><br />
Threads collide, if you use semaphores / mutexes you will prevent it from happening but, after adding 5 threads to process data from a queue, there is no performance improvement because threads have to wait each-other. It was a design fault, to continue increasing performance I had to add more queues with different semaphores so the threads wont collide so much, so that brings me to the last version:<br />
<br />
<br />
<br />
<b><Version Number 0.1.12:></b><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0_4w-G7iV4iYWLpQ28YBE8wjgno5ECypwawZcZgopwFCdEZzfrcGujvOZQEBrK9Y7kGcvXRaR9vwg-DJnAlvbhYQA5DTTmRhVrhamlhfZCGUc2q9YWRhdes0YltJUJQfUpk5quYWLfH77/s1600/StressTest897clients.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="465" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0_4w-G7iV4iYWLpQ28YBE8wjgno5ECypwawZcZgopwFCdEZzfrcGujvOZQEBrK9Y7kGcvXRaR9vwg-DJnAlvbhYQA5DTTmRhVrhamlhfZCGUc2q9YWRhdes0YltJUJQfUpk5quYWLfH77/s640/StressTest897clients.png" width="640" /></a></div>
<br />
<i><867 Clients connected at the same time, everyone constantly moving sending data to the server, 25 incoming packets /s per client, total, +2.000 incoming messages processed/s, peak:18.000 messages SENT in a second, that is like 18 packets /millisecond, latency/lag for the clients from 49ms to 113ms average 70-80ms></i><br />
<br />
<br />
<br />
<b>Classes:</b><br />
<br />
<ul>
<li>cSockServer: Stores global data , a vector to store all the clients connected, server socket, etc...<br />
</li>
<li>cSockClient:Stores data for every client such as socket to communicate</li>
</ul>
<b>Threads:</b><br />
<ul>
<li>1x Master thread: Master thread listen for the clients and assigns a new socket to everyone.</li>
<li>2xProcessor threads:It processes the data into the input queue and updates wold data</li>
<li>1xUpdater Thread: inserts clients with updated data to a queue to update</li>
<li>4xUpdaterQueues:it gets the client UID from the UpdaterQueue and check which clients are near and need to get an update state, so it inserts the outgoing data to the Pool of Output queues
</li>
<li>Pool of Sender threads:The thread gets data from the Pool of Queues and Send data to the clients</li>
<li>1xListener Thread/Client:listen for incoming data and inserts it into the Input queue.</li>
</ul>
<b>Queues / vectors:</b><br />
<ul>
<li>Clients vector:Here I store clients data (sockets, UIDs, etc)<br />
</li>
<li> Input queue:One in the server, used to store incoming data</li>
<li><vector>Pool Output Queue:It can handle many queues so if the client number rise, you can add more queues to prevent thread collisions.</li>
<li><vector>Pool Sender thread Queue: Used to store / add Sender threads dynamically.</li>
</ul>
<b>Good things of the design:</b><br />
<ul>
<li>Finally threads start to unleash their power, as many threads / output queues you add, as many users can handle, 867 clients (BOTs) are starting to be something good for a server.... </li>
</ul>
<br />
<b>Bad Things of the design: </b><br />
<ul>
<li>No optimized at all, there are many parts in the server that could change to make it work smoother, but for didactic purposes, I wont change them at the moment.</li>
</ul>
<b>What I learned from this version:</b><br />
I have learned to be very careful with the threads, many threads can access to a variable and read from it and processing power will go up, but when writing data you are forced to use semaphores, so speed stops increasing after a certain number of threads.<br />
<br />
I added a command for the server that was "AddPower" it adds one output queue and 5 sender threads, so you can adjust performance, but speaking with a friend he told me that I could automate it so automatically it added more queues /threads, so I did! checking if the queues were filled and needed to be processed faster was easy, and the result is the server you have in the picture absorving 867 clients data....<br />
<br />
Thanks Jhonny D!<br />
<br />
See you soon in the MMORPG series....Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-58828892857653711792011-11-18T20:04:00.001+01:002011-11-18T23:11:11.365+01:00Debian Versus Kubuntu Versus Windows 8Debian 6.03<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMz_k93pKssIdGJd2eDQuXs_buWAuFQ5SSwES2DVvy0_NYsWdaTiY1viP5S7M1rW6UIDAoK4Zxv16FsRuQCu9xKSQuL5daVfvdv8N0tIEdpb5IUs6VgMa3UokSr7cPbLb6O2NJii2ajpqo/s1600/debian.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMz_k93pKssIdGJd2eDQuXs_buWAuFQ5SSwES2DVvy0_NYsWdaTiY1viP5S7M1rW6UIDAoK4Zxv16FsRuQCu9xKSQuL5daVfvdv8N0tIEdpb5IUs6VgMa3UokSr7cPbLb6O2NJii2ajpqo/s1600/debian.png" /></a></div>
<br />
Kubuntu 11.10<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbIrd5pGthsiU58NdrF_9mr4yk0ZTYAc0NhQMHT2pWWBEceTJ9fJli4AnCR-PLu3K1vq3bkS4zLBjVXAVJoe_YKdqO9M6gmF_z-feOKI_2-Y8-GeTCzrSCWas0dN06QDSobjcx9DpW4fTF/s1600/kubunu1110.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbIrd5pGthsiU58NdrF_9mr4yk0ZTYAc0NhQMHT2pWWBEceTJ9fJli4AnCR-PLu3K1vq3bkS4zLBjVXAVJoe_YKdqO9M6gmF_z-feOKI_2-Y8-GeTCzrSCWas0dN06QDSobjcx9DpW4fTF/s1600/kubunu1110.png" /></a></div>
<br />
Windows 8 beta developer preview<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCRE_uNpbRoubi5c9FHscT0pD6KD6IBco4KNU9AHVuoUKhhbVLelV5msgJO7Q2C1FqVrFzXjaeAk23PZWCpnzEshqllxpG3bksjFkJkPNTBINy-rFCDllIA0s2LQblGoEUYGoc7IeZNo2-/s1600/windows8.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiCRE_uNpbRoubi5c9FHscT0pD6KD6IBco4KNU9AHVuoUKhhbVLelV5msgJO7Q2C1FqVrFzXjaeAk23PZWCpnzEshqllxpG3bksjFkJkPNTBINy-rFCDllIA0s2LQblGoEUYGoc7IeZNo2-/s1600/windows8.png" /></a></div>
<br />
In the last weeks I have tried many "new" OSes, the first one was Kubuntu 11.10:<br />
<br />
After the decision from the Ubuntu team to use Unity in the standard distro 11.04 I have been waiting to see if in the 11.10 version all the mistakes have been removed, unfortunately I had exactly the same feeling that with the previous version...<br />
<br />
One of the things I like from Linux is the freedom: freedom to choose what do you want to install and how to configure it to adapt to your personal tastes and needs<br />
<br />
With the infamous Unity I feel like if I was a toy inside a Box: I can see beautiful glitter-filled walls, but I can't see anything else!, I thing that when in your process table Xorg is taking MORE CPU than your mmorpg server, something is completely wrong..<br />
<br />
I downloaded and installed Kubuntu 11.10, hell I don't like windows-style from KDE but I was so disgusted with regular "Unitybuntu 11.10" that I decided to try it... now I regret I didn't went for Debian before..<br />
<br />
Debian is the mother of Ubuntu, and many other Linux flavors, but I have been always afraid to download the tons of gigabytes the full distro uses, but when I entered www.debian.org last day I realized the network installer only occupied like 400 MB, so I downloaded , burned and installed it..<br />
<br />
When I did I felt like my first times with Linux (with Slackware), everything was not made "for dummies", you had to set up many things, like repositories to be able to install apps, but well after goggling a bit I was able to install all the tools I use day by day....<br />
<br />
It is not as beautiful as Ubuntu or Kubuntu but now my CPU cycles are used for my apps, not for openGL....<br />
<br />
<br />
I downloaded today Windows 8 beta developer preview and installed it, after all the things I have heard from it I was almost sure it's gonna be very different from Windows 7, but all the people that has been MS OSes since a few years ago will realize it shares many things from previous versions, the feeling I got from it is that it was completely designed not for pcs, but for Tablets... yes, forget about pcs, the interface is made so you can use it with a touch screen...<br />
<br />
Another thing is forget to use it with any computer with less than a 2 dual core fast (2Ghz+ processor) with 2 GB RAM, I installed it in a virtual computer and it took 5 minutes to boot using one core from my I5 core processor (3.2Ghz), assigning the 4 cores to Windows made it boot in "only" 2 minutes... OMG! I hope MS optimize it.. or get ready for a "Vista 8"....<br />
<br />
Well I have to test it more but the first feeling is Microsoft wants to change mind of the users.. again, time will say if they are right...<br />
<br />
<br />
Well , enough OS review for today..<br />
<br />
See you!Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-34962401430367303502011-11-15T21:39:00.001+01:002011-11-15T23:06:05.598+01:00So I want make an MMORPG, Where do I start from? PART 1That is indeed a good question, asked so many times and answered many times too, in many sites the answer is like:<br />
<br />
<If you have a team><br />
<ol>
<li>Get a team: coders + artists + world designers +well like 10 persons.</li>
<li>Get ready to expend 2 years (at least) on it</li>
<li>Pay big amount of money to the ISP</li>
<li>Have a design document </li>
</ol>
<Lone developer><br />
<ol>
<li> Forget about it :(</li>
</ol>
What can I add to that? I basically decided to made it no matter how hard it was; I'm not somebody that has never programmed and think that their "RPG maker experience is enough", I'm not asking how to make it because If you are asking that, you probably are so far from the objective you desire that you wont get it never.<br />
<br />
I tried to divide the BIG puzzle into small pieces, c++, SDL, SDL_image, SDL_ttf, SDL_NET, SDL_thread, Gimp, MYSQL....<br />
<br />
With those pieces I made some bigger ones: A tileset, a simple game engine, game states, player creation process, a simple chat server....<br />
<br />
And now it comes the good thing, I got a Simple (RPG DEMO) server with a client, I didn't made it on time (1 year was my objective), but now , after millions of doubts I know I will finish the game...<br />
<br />
My objectives now are:<br />
<ol>
<li> Start a series of posts explaining how I did it. </li>
<li>Clean Server / client code and upload them (Yes, I'm going to release it soon)</li>
<li>Set up MYSQL server</li>
</ol>
So first thing first:<br />
<br />
<b>Q</b>:What do I need to learn to send / receive date across the network?<br />
<b>A</b>:Network sockets<br />
<br />
<b>Q</b>: How does network sockets work?<br />
<b>A</b>: Network sockets handles data send/received to an IP network, they are both used by TCP (Connection oriented ) and UDP (Connectionless oriented), in the server you "open" a socket to listen for incoming data, open a socket means bind the program to a particular IP port of the computer, so we could open a socket at port 80 to create a web server, for example, when we create a server socket it waits until a Client machine (program) connects to it, then we create a client sockets that is going to actually communicate with the client. The clients just open a client socket and establish a connection with the server socket.<br />
<br />
<b>Q</b>:Why do I need threads?<br />
<b>A</b>: Threads are used to do many things at the same time, for example, a Client for the MMORPG, could have a thread to draw the images on the screen while another one sends/receives network data , the server could have one thread (maybe more?) to handle network data, another one for the AI, another one for Environment events... In the modern multi-core computers, it's a way to use 100% of the processor power<br />
<br />
<b>Q</b>:Why are you using SDL_NET? isn't it an ancient library?<br />
<b>A</b>:It is old, but network sockets are older and are still used today (and probably are going to be used for many, many years), just thing the new IP protocol (IPv6) uses them too... SDL_NET has other advantages too, it can be used in a multi-platform environment (I use it in my client and I can compile it under windows / Linux without touching a single line from the code to make it work :) ), finally it is a low-level library so you feel you have the control over what you are working, there are libraries made upon SDL_NET that add things (NET2 uses multi-threading for example), but you have less control about what is happening, another problem is find documentation , SDL_NET is so small that when you read the manual , you realize how easy is to use it.<br />
<br />
<More Q/A soon...><br />
<br />
In the next post: Server code and explanations..<br />
<br />
JB<br />
<ol>
</ol>Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-50658466086455855792011-11-11T00:01:00.001+01:002011-11-15T23:04:58.298+01:00RPG Client Alpha!!!<Client V0.11><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUp9-5bH8kBBpzCrM5IHaxER4sHNAFgzBg70b90fqs-czVl4jR316AqnPTCA_M1GzODP6bJoApm0BQCcIM53cu_eMY4epdg9-rqatPXkgIgoApdKF7C47epYDK2oK-1v9yF5-TGfKLBwsC/s1600/InGame.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="497" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUp9-5bH8kBBpzCrM5IHaxER4sHNAFgzBg70b90fqs-czVl4jR316AqnPTCA_M1GzODP6bJoApm0BQCcIM53cu_eMY4epdg9-rqatPXkgIgoApdKF7C47epYDK2oK-1v9yF5-TGfKLBwsC/s640/InGame.png" width="640" /></a></div>
<br />
<Client V0.1><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGchZXylxxyuXW4WJQ-eoSl3Fo07XQnlA5wzQhZ67gGvtI391qkBe0bcFytpEJJqTIGayl213migTjnuTFBCXeFUNYadPXjaPXYKtiqXG8BgNSnK3sdX9td2dgGsvJCKK2Xg7nc598zujc/s1600/rpg+client+alpha.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgGchZXylxxyuXW4WJQ-eoSl3Fo07XQnlA5wzQhZ67gGvtI391qkBe0bcFytpEJJqTIGayl213migTjnuTFBCXeFUNYadPXjaPXYKtiqXG8BgNSnK3sdX9td2dgGsvJCKK2Xg7nc598zujc/s640/rpg+client+alpha.png" width="640" /></a></div>
<doesn't it="" look="" nice?=""><Doesn't it looks nice??></doesn't><br />
<doesn't it="" look="" nice?=""><br />
</doesn't><br />
<doesn't it="" look="" nice?="">So after two weeks fighting against the elements I have been able to connect my Rpg Demo with the chat server (and basically modifying all the code), but now you can move around with your own player...</doesn't><br />
<doesn't it="" look="" nice?=""><br />
</doesn't><br />
<doesn't it="" look="" nice?="">You can't do much things, in fact you can just MOVE, but that's exactly the base where I wanted to start from.</doesn't><br />
<doesn't it="" look="" nice?=""><br />
</doesn't><br />
<doesn't it="" look="" nice?="">I have uploaded the Windows version binaries so basically everybody (windows /linux + wine) can test it, just go to the <a href="http://jbfproject.blogspot.com/p/downloads.html">downloads</a> page and get it!</doesn't><br />
<br />
<doesn't it="" look="" nice?=""><span style="color: red;">For alpha testers</span>: To test it, you are going to need an IP number, PM please so I will tell you...</doesn't><br />
<doesn't it="" look="" nice?=""><br /></doesn't><br />
<doesn't it="" look="" nice?="">See you</doesn't><br />
<doesn't it="" look="" nice?=""><br />
</doesn't><br />
<doesn't it="" look="" nice?=""><br />
</doesn't>Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-14008616863425448052011-11-05T00:44:00.003+01:002011-11-08T23:30:56.488+01:00A Simple chat server, code uploaded...<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEDx8WH6IKBaE54XS1BhgLHdTgOad6E_6xXkdj_zKIHWcDscYXyJL-X3FgslLHA9vqxs4-c5Tl-MII01zEW5JXwfSjy-SpPbNFCCIEL7qNaoL7K-Pxc2NHo44Uw19raURT2vNA9vl8gTJd/s1600/chat+server.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEDx8WH6IKBaE54XS1BhgLHdTgOad6E_6xXkdj_zKIHWcDscYXyJL-X3FgslLHA9vqxs4-c5Tl-MII01zEW5JXwfSjy-SpPbNFCCIEL7qNaoL7K-Pxc2NHo44Uw19raURT2vNA9vl8gTJd/s400/chat+server.png" width="400" /></a></div>
<A chat server / client><br />
<br />
<br />
I've just uploaded the full code for the simple chat server and client projects, it is a very simple project, but shows the core needed to create a server including multi-threading and connections /disconnections from clients.<br />
<br />
At the moment the clients can do:<br />
<ul>
<li>Send messages to other clients.</li>
<li>Send private messages to another client (/priv nick message)</li>
<li>Ask for the list of connected users (/List)</li>
<li>Change nick (/nick newnick)</li>
<li>And of course, exit the server (/quit)</li>
</ul>
I don't have plans to upgrade the chat server, instead I'm going to adapt it so many players can connect with a client (rpg demo 4) to the server and anybody can walk around and chat.... That is my next milestone, when I achieve it I'll enable the fights to spice it a little ;) <br />
<br />
JBAnonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-56385042690008110932011-10-24T22:52:00.002+02:002011-10-24T22:54:46.408+02:00New Downloads / Windows BinariesHello!<br />
<br />
<a href="http://jbfproject.blogspot.com/p/downloads.html">New downloads!</a><br />
<br />
<One year ago I started this project with many objectives, one of them was to make it multi-platform so yesterday I decided to compile my projects under Windows, or at least try to do it...><br />
<br />
<And here it comes the ingredients for my Windows recipe:<br />
<ol>
<li>A virtual machine emulator (a.k.a. <a href="http://www.virtualbox.org/">Virtualbox</a> ), Somebody will prefer a dual-boot configuration or just Windows, well, it's up to you...</li>
<li>A Windows installation disk, you have one, right? (Important: First, clean the dust)</li>
<li><a href="http://www.virtualbox.org/">Code::Blocks 11.05 compiler + minGW</a> (Install, Next > Next > Next > Next > Finish.... Windows is SO user-friendly...)</li>
<li>An assorted mix of <a href="http://www.libsdl.org/">libSDL libraries</a> (SDL, SDL_image,SDL_ttf,SDL_net): Download, extract, and then mix them so you put all \include and all \lib files together, and of course the DLLs too.</li>
<li>Download the sources too..</li>
<li>If you want to compile them you will have to set up the compiler so it uses the sdl\include and sdl\lib paths, other way, it will simple refuse to work.</li>
</ol>
Another important thing is that you have to change all the includes:<br />
<br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include "SDL/SDL.h"
#include "SDL/SDL_image.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_net.h"
#include "SDL/SDL_thread.h"
</pre>
</div>
<br />
In all the source files with:<br />
<br />
<br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>#include "SDL.h"
#include "SDL_image.h"
#include "SDL_ttf.h"
#include "SDL_net.h"
#include "SDL_thread.h"
</pre>
</div>
<br />
(paths are a little bit different under Windows..)<br />
<br />
<And well, that's it! after doing that I got the life game and the three rpg sub-projects working ><br />
<br />
<<i>I wanted to include the chat server / client project too</i>, hey ! I really wanted to do, but I found an unexpected and silly problem, the chat server uses the std input / output for everything, I cout << what the clients "say" and get cin >> the clients input, it works fine under Linux, but under Windows, it redirects the output and errors too to the files "<span class="st">stdout.txt/stderr.txt</span>", it is the normal behavior, if you are making a graphical project, you don't have the console, right? but what if you need it?><br />
<br />
<I have been goggling for solution and finally I found something that should work: > <br />
<br />
<br />
<div ;="" id="code" style="background-color: #aaaaff; border: 1px none rgb(17, 17, 17); color: #333333;">
<pre>SDL_Init(SDL_INIT_VIDEO);
if (ctt)
{
freopen("CON", "w", stdout);
freopen("con", "w", stderr);
fclose( ctt );
}
</pre>
</div>
<br />
<That was supposed to set the output again to console, I added the code, and when I executed the project under code::blocks, It magically worked again, so I happily rebuild the project...><br />
<br />
<And then I executed the resulting .exe, it opened a console window... (have I said it was black? completely black?) :(, that's when I decided I wont compile it for Windows ( at the moment), if anybody had found that problem and feels eager to help, I will really appreciate it...><br />
<br />
<In the next post, the chat server /client...><br />
<br />
<br />
See you<br />
JBAnonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com0tag:blogger.com,1999:blog-1792734122980275490.post-70956740827374719642011-10-13T23:32:00.003+02:002011-10-17T00:11:46.127+02:00SDL_net / SDL_threads(1): The Threading beast, is it so dangerous?<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU6KcVcHrZYsKTVATmgUZARJtTyN60uRK-piAzEsNCmlOqHCAszmsuNfCjGSnWBHWqCgbR8b6HpbmfuC48MoeGjZE4k74ywRGQjRPD1Q6dZmsXy_6IXN-sMvwwsG9zs6WGJHhpi4J4ZsJW/s1600/sockserver1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgU6KcVcHrZYsKTVATmgUZARJtTyN60uRK-piAzEsNCmlOqHCAszmsuNfCjGSnWBHWqCgbR8b6HpbmfuC48MoeGjZE4k74ywRGQjRPD1Q6dZmsXy_6IXN-sMvwwsG9zs6WGJHhpi4J4ZsJW/s640/sockserver1.png" width="640" /></a></div>
A multi-threaded echo server....<br />
<br />
<What is the most important thing beyond every mmorpg? is it the history?, maybe the fancy 3d graphics? nope... it is the network play!><br />
<br />
<When I started the project , one year ago my objective was to bring the game on-line, I just didn't thought how many new things I needed to learn, the C++ language , the libSDL library, all the other extension libraries (SDL_image, SDL_ttf, SDL_net, SDL_thread, ...), how to use blogger... , the Gimp, etc, etc....><br />
<br />
<It has been a long trip, but now I have arrived where I wanted to be, to the network><br />
<br />
<On the top of the page there is an screen-shot showing my first networking demo, a multi-threaded socket server using SDL_net and SDL_thread><br />
<br />
<I start the server and then I can connect with telnet to the server, every thing I type on the telnet window goes to the server and it returns the message to the sender, maybe you can think it is something too easy, but let me show why it's important...><br />
<br />
<Here what you can't see is more important than what you see, that's the project structure:><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTyuHraYpDlxHmOorR1juDjtTvW9EzlIcd9M63OPDNXdkohiKeLV5vLwRRBgGVffkddy2aysY9ZvPsWkkKdx99hDjCGwCfqqlvZTTo8ARz0CPXVXDV5n3cQ4OnBUpgJKUjYMCw2vpeGPHT/s1600/echo_server.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="390" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTyuHraYpDlxHmOorR1juDjtTvW9EzlIcd9M63OPDNXdkohiKeLV5vLwRRBgGVffkddy2aysY9ZvPsWkkKdx99hDjCGwCfqqlvZTTo8ARz0CPXVXDV5n3cQ4OnBUpgJKUjYMCw2vpeGPHT/s400/echo_server.png" width="400" /></a></div>
<br />
<I encapsulate all the network code into two classes: csockserver and csockclient, fist one opens an SDL_net server socket who is going to sit and wait for incoming connections, when it happens (new client connection), it creates a new csockclient and adds it to the vector, then the csockclient starts a thread and the thread wait for data incoming to the server for a client, when it happens it just echoes the data back to the client><br />
<br />
<it is a very simple way to handle data, a perfect base to start adding new features, now if we change just a few lines we will have a chat server, but threaded><br />
<br />
<I have remarked the thread thing because when I started to look for demos / tutorials to use SDL_net I basically found nothing related to using it with threads, the question is a server needs threads, we can't stop the server logic just to see if a client is sending data, and for the server I'm going to use more threads: (for example , for the A.I.) so many things can happen at the same time, making threaded code is very hard, because any small mistake is going to crash the server, make your computer leak memory, or even worse open a security hole....><br />
<br />
<I'm going to finish the next step (the chat server) and I will post the c++ code><br />
<br />
<Ideas / suggestions are always welcome><br />
<br />
<see you, in the chat><br />
<br />
JB<br />
<br />
<B.T.W. Ogres are ugly, SDL_net + threads too, what could happen if you mix them?? ;)>Anonymoushttp://www.blogger.com/profile/03532692006846889189noreply@blogger.com1